2017-01-21 16 views
1

私は、JWT認証とウェブソケットを使用している小さな.netコアアプリケーションに取り組んでいます。websocketリクエスト中にJWTを検証する方法。 .net core

私は、標準のWeb APIコントローラのトークンの生成と検証を成功裏に実装しました。しかし、WebSocketリクエストのトークンを検証して、もちろん[Authorize]属性では動作しないようにしたいと考えています。

は、私は私のミドルウェア・パイプラインのように設定している:

app.UseWebSockets(); 
app.Use(async (http, next) => { 
     if (http.WebSockets.IsWebSocketRequest == false) { 
      await next(); 
      return; 
     } 
     /// Handle websocket request here. How to check if token is valid? 
}); 

// secretKey contains a secret passphrase only your server knows 
var secretKey = .....; 
var signKey = new SigningCredentials (
    new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secretKey)), 
    SecurityAlgorithms.HmacSha256 
); 

var tokenValidationParameters = new TokenValidationParameters { 
    ValidateIssuer = false, 
    ValidateAudience = false, 

    // The signing key must match! 
    ValidateIssuerSigningKey = true, 
    IssuerSigningKey = signKey.Key, 

    // Validate the token expiry 
    ValidateLifetime = true, 

    // If you want to allow a certain amount of clock drift, set that here: 
    ClockSkew = TimeSpan.FromMinutes(1), 
}; 


app.UseJwtBearerAuthentication(new JwtBearerOptions { 
    AutomaticAuthenticate = true, 
    AutomaticChallenge = true, 
    TokenValidationParameters = tokenValidationParameters 
}); 

答えて

4

私はポストが古いの一種であるにも関わらず、これが誰かを助けることができると思います。

私はグーグルではなく答えを見つけましたが、ビンディング!私はthis official codeから自分自身をインスパイアしました。

JwtBearerOptionsのマジックを使用して、承認を処理する独自のクラスを簡単に作成できます。このクラスにはJWTの検証に必要なものがすべて含まれています。

したがって、サービスとして注入するだけでなく、それを使用して認証を設定する必要があります。あなたのStartup.ConfigureServicesでそのような何か:

this.JwtOptions = new JwtBearerOptions 
     { 
      AutomaticAuthenticate = true, 
      AutomaticChallenge = true, 
      TokenValidationParameters = yourTokenValidationParameters 
     }; 
services.AddSingleton<JwtBearerOptions>(this.JwtOptions); 

はその後、あなたはあなたのつもりトークン(This is where my code was inspiredを)検証されたクラスを作成する必要があります。 バッカー

public class JwtBearerBacker 
{ 
    public JwtBearerOptions Options { get; private set; } 

    public JwtBearerBacker(JwtBearerOptions options) 
    { 
     this.Options = options; 
    } 

    public bool IsJwtValid(string token) 
    { 
     List<Exception> validationFailures = null; 
     SecurityToken validatedToken; 
     foreach (var validator in Options.SecurityTokenValidators) 
     { 
      if (validator.CanReadToken(token)) 
      { 
       ClaimsPrincipal principal; 
       try 
       { 
        principal = validator.ValidateToken(token, Options.TokenValidationParameters, out validatedToken); 
       } 
       catch (Exception ex) 
       { 
        // Refresh the configuration for exceptions that may be caused by key rollovers. The user can also request a refresh in the event. 
        if (Options.RefreshOnIssuerKeyNotFound && Options.ConfigurationManager != null 
         && ex is SecurityTokenSignatureKeyNotFoundException) 
        { 
         Options.ConfigurationManager.RequestRefresh(); 
        } 

        if (validationFailures == null) 
         validationFailures = new List<Exception>(1); 
        validationFailures.Add(ex); 
        continue; 
       } 
       return true; 
      } 
     } 
     return false; 
    } 
} 

次に、あなたのミドルウェアでは、単にリクエストヘッダ、JwtOptions依存関係にアクセスして呼び出します:また

protected string ObtainAppTokenFromHeader(string authHeader) 
    { 
     if (string.IsNullOrWhiteSpace(authHeader) || !authHeader.Contains(" ")) 
      return null; 
     string[] authSchemeAndJwt = authHeader.Split(' '); 
     string authScheme = authSchemeAndJwt[0]; 
     if (authScheme != "Bearer") 
      return null; 
     string jwt = authSchemeAndJwt[1]; 
     return jwt; 
    } 

    protected async Task<bool> AuthorizeUserFromHttpContext(HttpContext context) 
    { 
     var jwtBearerOptions = context.RequestServices.GetRequiredService<JwtBearerOptions>() as JwtBearerOptions; 
     string jwt = this.ObtainAppTokenFromHeader(context.Request.Headers["Authorization"]); 
     if (jwt == null) 
      return false; 
     var jwtBacker = new JwtBearerBacker(jwtBearerOptions); 
     return jwtBacker.IsJwtValid(jwt); 
    } 

    public async Task Invoke(HttpContext context) 
    { 
     if (!context.WebSockets.IsWebSocketRequest) 
      return; 
     if (!await this.AuthorizeUserFromHttpContext(context)) 
     { 
      context.Response.StatusCode = 401; 
      await context.Response.WriteAsync("The door is locked, dude. You're not authorized !"); 
      return; 
     } 
//... Whatever else you're doing in your middleware 
     } 

を!彼はあなたの背中を持っているためのは、バッカーそれを呼ぶことにしましょうAuthenticationTicketとauthに関するその他の情報は、すでにフレームワークのJwtBearerMiddlewareによって処理されていて、とにかく返されます。

最後に、クライアント側。実際に追加のHTTPヘッダーをサポートするクライアントライブラリを使用することをお勧めします。たとえば、私が知る限り、W3C Javascriptクライアントはこの機能を提供しません。

ここにあります!オープンソースのコードベースのMicrosoftに感謝します。

+0

ありがとう。それが再び現れたら、私はこれを将来使用します! –

関連する問題