2017-01-04 66 views
0

我在我的ASP .NET核心應用程序中實現了一個cookie身份驗證模塊作爲中間件。我收到一個錯誤「InvalidOperationException:在上一個操作完成之前,在此上下文中啓動了第二個操作,但不保證所有實例成員都是線程安全的。」兩個請求幾乎同時發生(在函數CheckToken中)。我相信每個請求都應該收到一個單獨的數據庫上下文,所以我不明白爲什麼會發生此錯誤。異步實體框架數據庫訪問失敗,例外(ASP .NET核心)

Startup.cs

public void ConfigureServices(IServiceCollection services) 
{ 
    services.AddDbContext<ApplicationDbContext>(options => 
     options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); 
    // ... 


public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 
{ 
    // ... 
    app.UseTeamAuthentication(); 
    // ... 

中間件

namespace Team 
{ 
    public static class TeamExtensions 
    { 
     public static IApplicationBuilder UseTeamAuthentication(this IApplicationBuilder builder) 
     { 
      return builder.UseMiddleware<TeamAuthentication>(); 
     } 
    } 

    public class TeamAuthentication 
    { 
     private readonly RequestDelegate next; 
     private readonly ApplicationDbContext db; 

     public TeamAuthentication(RequestDelegate _next, ApplicationDbContext _db) 
     { 
      next = _next; 
      db = _db; 
     } 

     public async Task Invoke(HttpContext context) 
     { 
      bool Authenticated = false; 
      bool Login = (context.Request.Path == "/Login"); 
      string TokenContent = context.Request.Cookies["t"]; 

      if (!Login && TokenContent != null) 
      { 
       int UserID = await Security.CheckToken(db, TokenContent); 
       if (UserID > 0) 
       { 
        Authenticated = true; 
       } 
      } 

      if (Login || Authenticated) 
      { 
       await next.Invoke(context); 
      } 
      else 
      { 
       context.Response.StatusCode = 401; 
       if (context.Request.Headers["X-Requested-With"] != "XMLHttpRequest") 
       { 
        await context.Response.WriteAsync("No access!"); 
       } 
      } 
     } 
    } 
} 

CheckToken

public async static Task<int> CheckToken(ApplicationDbContext db, string Content) 
{ 
    var token = await db.Token.FirstOrDefaultAsync(m => m.Content == Content); 
    if (token != null) 
    { 
     if (DateTime.Now < token.Expiry) 
     { 
      token.Expiry = DateTime.Now.AddHours(1); 
      await db.SaveChangesAsync(); 
      return token.UserID; 
     } 
     else 
     { 
      db.Token.Remove(token); 
      await db.SaveChangesAsync(); 
      return 0; 
     } 
    } 
    else 
    { 
     return 0; 
    } 
} 

回答

0

您不應該在構造函數中請求ApplicationDbContext。這將導致只有一個DbContext實例可用於所有請求和類似於您的錯誤。

var db = context.RequestServices.GetRequiredService<ApplicationDbContext>(); 
0

您注射數據庫上下文到中間件。但我想中間件是每個應用程序創建一次,而不是每個請求。這就是爲什麼所有請求都會在中間件內獲得相同的數據庫上下文

+0

好吧,如果是這樣的話,就不會(功能)DB: - (每個DI一次範圍更精確)這裏面的代碼Invoke方法

相反,獲得獨立的DbContext爲每個請求在中間件訪問是不可能的?中間件身份驗證如何在這種情況下工作? – Marko

+0

我認爲這是可能的。嘗試添加依賴到'Invoke'方法中,而不是構造函數,比如'public async Task Invoke(HttpContext context,ApplicationDbContext db)' –

相關問題