2017-09-05 18 views
2

最初の.netコア2 Webアプリケーションの実装を開始しました。残念なことにビジネス要件のために、ユーザーはレガシー・フォーム・ログインを介して認証する必要があり、ユーザー名/パスワードはoracle dbに処理され、ユーザーが認証されるとセッションIDが生成され、起動されたアプリケーションのベースURLに追加されます。非常に古い学校ですが、それは動作します。ClaimsIdentity with .NET Core 2ミドルウェアソリューション

セッションIDが期限切れになるので、私のアプリで検証する必要があります。簡単ですが、私はクエリ文字列から取得したセッションIDをOracle APIに渡します。レスポンスはファーストネーム、ラストネームなどのユーザー情報を含むオブジェクトです。

このAPI呼び出しが正常に完了したら、新しいClaimsIdentityとPrincipalを呼び出し、SignInAsync()メソッドを呼び出します。

私は現在、自分のStartup.csに登録したカスタムミドルウェアでこれを行います。私はこれを通常のLogin Controllerメソッドで扱いますが、アプリケーションにログインがないので、私は他の方法を見ることはできませんが、私が書いたミドルウェアではありません。

public class AuthenticationHandler 
{ 
    private readonly RequestDelegate _next; 
    private HttpService _httpService; 

    public AuthenticationHandler(RequestDelegate next, HttpService httpService) 
    { 
     _httpService = httpService; 
     _next = next; 
    } 

    public async Task Invoke(HttpContext context, [FromServices] HttpService httpService) 
    { 
     if (context.Request.Query.Count == 1) 
     { 
      var sessionId = context.Request.Query.FirstOrDefault().Value; 
      var session = await _httpService.ValidateSession(sessionId); 

      if (!string.IsNullOrEmpty(session?.UserId)) 
      { 
       var claims = new List<Claim>() 
       { 
        new Claim(CustomClaimTypes.UserId, session.UserId), 
        new Claim(CustomClaimTypes.BuId, session.BuId), 
        new Claim(CustomClaimTypes.SecurityLevel, session.SecurityLevel) 
       }; 

       var identity = new ClaimsIdentity(claims, "TNReadyEVP"); 
       var principal = new ClaimsPrincipal(identity); 

       await Microsoft.AspNetCore.Authentication.AuthenticationHttpContextExtensions.SignInAsync(context, principal); 

       var isIn = principal.Identity.IsAuthenticated; 
       var isAuthed = (context.User.Identity as ClaimsIdentity).IsAuthenticated; 
       await _next.Invoke(context); 
      } 
      else 
      { 
       Terminate(context); 
      } 
     } 

     return; 
    } 

    private async void Terminate(HttpContext context) 
    { 
     context.Response.StatusCode = 401; 
     await context.Response.WriteAsync("Invalid User"); 
     return; 
    } 
} 

public static class MiddlewareExtensions 
{ 
    public static IApplicationBuilder ValidateSession(this IApplicationBuilder builder) 
    { 
     return builder.UseMiddleware<AuthenticationHandler>(); 
    } 
} 

これまでのところ、これは正しい解決策だと私は信じています。しかし、私は私のアプリでは、以下のように、クレームは空であり、User.Identity.Authenticatedはfalseである小さなAPIを介してクレームを取得しようとするとfalseです。

私はここで何が欠けていますか?アドバイスをありがとう、これは私が前に対処していなかったそれらの奇妙なエッジケースの一つです...したがって、カスタムミドルウェアの必要性。

[HttpGet("claims")] 
    public async Task<IEnumerable<Claim>> Get() 
    { 
     var claims = (User as ClaimsPrincipal).Claims; 
     return await Task.FromResult(claims); 
    } 

答えて

1

本当に自分のミドルウェアを使用するべきではありません。組み込みの認証と認可スタックは、あなたの状況を処理するのに十分強力です。実際、Barry Dorrans氏(ASP.NETセキュリティPM)は、ASP.NETコアプロジェクトの認証スタックを担当しています。basically† said in a talkあなたのユースケースでうまくいかない場合、電子メールをドロップして修正する必要があります。

代わりに、この目的のために独自の認証ハンドラを作成することを検討する必要があります。そうすれば、追加のハードルを必要とせずに認証および認可のインフラストラクチャ全体を手に入れることができます。すべてがうまくいくでしょう。

これを行うには、基本的にIAuthenticationHandlerを実装して登録する必要があります。

CookieAuthenticationHandlerは、あなたがしようとしているのと似たような仕事をしているからです。HTTPリクエストで送信された情報からクレームIDを再構築しています。クッキーデータの代わりにクエリ引数とデータベースを使用しているだけです。

一般的なアプリケーションフローをどのようにしたいのかによって、これをリモート認証プロバイダに変えて、クッキー認証と組み合わせることも考えられます.OAuthプロセスのように、あなたはリクエストを受け取ります。クッキーがない場合は、従来のログインマスクにリダイレクトするカスタム認証ハンドラに挑戦します。そこにログインすると、セッションIDが添付されたアプリケーションの特別なURL(例:/signin-session?sessionid=12345)に戻ります。リモート認証ハンドラは、その要求を処理し、データベースにクエリを行い、情報からアイデンティティを構築し、それをCookie認証ハンドラに渡します。そうすれば、アイデンティティを安全なクッキーに保持するので、すべてのリクエストでデータベースを照会する必要がなくなり、単一のURLごとにセッションIDも不要になります。

†公平になるために、彼はそこでの承認部分について話していました。しかし、本当に強力なので、彼はスタック全体を意味すると確信しています。

+0

詳細については、あなたは非常に有効な点を作っています。私が昨晩実験していたように、ミドルウェアを設計していない場合にミドルウェアを動作させようとしていたという結論に達しました。 CookieAuthenticationHandlerのドキュメントを確認し、これも調べてみましょう:https://docs.microsoft.com/en-us/aspnet/core/security/authentication/cookie?tabs=aspnetcore2x 私は基本的に大量のコードを持っています準備ができて、ただリファクタリングする必要があります。いくつかの他のエッジケースがあります。特定のURLパスがヒットしたときに認証プロバイダを起動するだけですが、それ以外にも良いスタートがあると思います...ありがとう! –

関連する問題