2016-05-10 6 views
4

ASP.Netコアのnoobでサービス/リポジトリメソッドの呼び出し...私はEF 6ここASP.Netコアミドルウェア

でDNX451を使用してASP.NetコアWebAPIのコアプロジェクトを使用しています、私は実装する必要があります私たちのサービスのAPIキーの認証。これを行うために、私はミドルウェアを作成しました。ミドルウェアはリクエストから情報を取得し、認証を続けます。データベースにアクセスし、一致するキーを取得してから、戻り、検証を実行することがサポートされています。ここで

はここ

public class AuthorizationHandler 
{ 
    private readonly RequestDelegate _next; 
    private IAuthenticationService _authenticationService; 

    public AuthorizationHandler(RequestDelegate next, IAuthenticationService authService) 
    { 
     _authenticationService = authService; 
     _next = next; 
    } 

    public async Task Invoke(HttpContext context) 
    { 
     try 
     { 
      var apiKey = context.Request.Headers["Key"]; 
      var location = context.Request.Headers["Host"]; 
      var locationKey = _authenticationService.GetApiKey(location); 

      if (apiKey == locationKey) 
       await _next(context); 


      context.Response.StatusCode = 403; 
      context.Response.Headers.Add("WWW-Authenticate", 
       new[] { "Basic" }); 

     } 
     catch (Exception ex) 
     { 
      context.Response.StatusCode = 500; 
      context.Response.Headers.Add("WWW-Authenticate", 
       new[] { "Basic" }); 
     } 
    } 
} 

AuthenticationHandler状況を見て、APIKEYに

を取得するために実装ミドルウェアは、コンテキストおよびミドルウェアの登録

public class Startup 
{ 
    public Startup(IHostingEnvironment env) 
    { 
     var builder = new ConfigurationBuilder() 
      .AddJsonFile("appsettings.json") 
      .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true); 


     builder.AddEnvironmentVariables(); 
     Configuration = builder.Build(); 
    } 

    public IConfiguration Configuration { get; set; } 

    // This method gets called by the runtime. Use this method to add services to the container. 
    public void ConfigureServices(IServiceCollection services) 
    { 
     services.AddScoped(k => new DbContext(Configuration["Data:Context:ConnectionString"])); 


     // Add framework services. 
     services.AddMvc(); 
    } 

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 
    { 
     loggerFactory.AddConsole(Configuration.GetSection("Logging")); 
     loggerFactory.AddDebug(); 

     app.UseIISPlatformHandler(); 

     app.UseStaticFiles(); 

     app.RegisterAuthorizationHeader(); 
     app.RegisterAuthorization(); 

     app.UseMvc(); 
    } 

    // Entry point for the application. 
    public static void Main(string[] args) => WebApplication.Run<Startup>(args); 
} 
とスタートアップクラスであります

ここに私私はこれをデバッグするとき、すべてのブレークポイントが二回ヒットされ、

The context cannot be used while the model is being created. This exception may be thrown if the context is used inside the OnModelCreating method or if the same context instance is accessed by multiple threads concurrently. Note that instance members of DbContext and related classes are not guaranteed to be thread safe.

:私は次のエラーを取得するこれをしようとすると認証サービス

public interface IAuthenticationService 
{ 
    string GetApiKey(string location); 
} 

public class AuthenticationService: IAuthenticationService 
{ 
    private IApiKeyRepository _apiKeyRepository; 
    public AuthenticationService(IApiKeyRepository repo) 
    { 
     _apiKeyRepository= repo; 
    } 

    public string GetApiKey(string location) 
    { 
     return _apiKeyRepository.GetApiKeyByLocation(location); 
    } 
} 

レポ

public interface IApiRepository 
{ 
    string GetApiKeyByLocation(string location); 
} 

public class ApiRepository: IApiRepository 
{ 
    private DbContext _context; 

    public ApiRepository(DbContext context) 
    { 
     _context = context; 
    } 

    public string GetApiKeyByLocation(string location) 
    { 
     var apiRow = _context.ApiKeyStore.FirstOrDefault(a => a.Location == location); 

     return apiRow == null ? string.Empty : apiRow.APIKey; 
    } 
} 

によ。 WHYこの問題は発生していますが、修正方法がわかりません。

誰かが私にアイデアをくれますか?どんな優れたソリューションアイデアですか?

答えて

4

が(必ずしも定義することにより、シングルトンである)ミドルウェアでスコープの依存関係を使用するには、最善のアプローチは、コンストラクタを介して、それを流すのではなく、InvokeAsyncのパラメータとして、それを流すことである。

public async Task Invoke(HttpContext context, IAuthenticationService authenticationService) 
{ 
    try 
    { 
     var apiKey = context.Request.Headers["Key"]; 
     var location = context.Request.Headers["Host"]; 
     var locationKey = authenticationService.GetApiKey(location); 

     if (apiKey == locationKey) 
      await _next(context); 


     context.Response.StatusCode = 403; 
     context.Response.Headers.Add("WWW-Authenticate", 
      new[] { "Basic" }); 

    } 
    catch (Exception ex) 
    { 
     context.Response.StatusCode = 500; 
     context.Response.Headers.Add("WWW-Authenticate", 
      new[] { "Basic" }); 
    } 
} 
+1

ありがとうございます!それは私が必要としていたものでした。 –

+0

ありがとうございました! 私はInvokeメソッドでDIを使用できるとは思いませんでした。同じコンテキストを使用する2つの同時リクエストで問題を解決しました。 – Thomas

関連する問題