2017-07-09 3 views
1

Ich wollte JWT-Authentifizierung in meiner MVC-App machen. Ich mache den Autorisierungs-Web-Service in der Web-API, der das Token korrekt zurückgibt. Danach versuche ich Token in Cookie zu speichern.Speichern von JWT-Token in Cookie in MVC 5

[HttpPost] 
    public async Task<ActionResult> Login(LoginDto loginDto) 
    { 
     var token = await loginService.GetToken(loginDto); 

     if (!string.IsNullOrEmpty(token)) 
     { 
      var cookie = new System.Web.HttpCookie("token", token) 
      { 
       HttpOnly = true 
      }; 
      Response.Cookies.Add(cookie); 
      return RedirectToAction("Index", "Product"); 
     } 
     return View("LoginFailed"); 
    } 

Aber jetzt wollte ich dieses Token Header für jede Anfrage hinzufügen. Also entschied ich, dass Action Filter am besten dafür geeignet wären.

public class CustomActionFilter : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     var token = filterContext.HttpContext.Request.Cookies.Get("token"); 

     if (token != null) 
      filterContext.HttpContext.Request.Headers.Add("Authorization", $"Bearer {token}"); 

     base.OnActionExecuting(filterContext); 
    } 
} 

Startup

public class Startup 
{ 
    public void Configuration(IAppBuilder app) 
    { 
     AutofacConfig.Configure(); 
     AreaRegistration.RegisterAllAreas(); 
     RouteConfig.RegisterRoutes(RouteTable.Routes); 
     FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 

     ConfigureOAuth(app); 
    } 

    public void ConfigureOAuth(IAppBuilder app) 
    { 
     var issuer = System.Configuration.ConfigurationManager.AppSettings["issuer"]; 
     var audience = System.Configuration.ConfigurationManager.AppSettings["appId"]; 
     var secret = TextEncodings.Base64Url.Decode(System.Configuration.ConfigurationManager.AppSettings["secret"]); 

     app.UseJwtBearerAuthentication(
      new JwtBearerAuthenticationOptions 
      { 
       AuthenticationMode = AuthenticationMode.Active, 
       AllowedAudiences = new[] { audience }, 
       IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[] 
       { 
        new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret) 
       }, 

      }); 

    } 
} 

Und dann habe ich gerade markiert Controller das Attribut autorisieren. Es funktioniert gut, als ich es mit POSTMAN angerufen habe.

Aber Action-Filter in MVC werden immer nach Autorisierungsfilter ausgelöst. So habe ich Fragen:

  1. Wie Token aus Cookie zu jeder Anfrage hinzufügen? Ist es eine gute Übung? Wenn nicht was ich tun sollte?
  2. Wie wäre es mit CSRF-Attacken und anderen? Wird AntiForgeryTokenAttr die Arbeit machen? Was ist mit Ajax ruft dann?

Antwort

0

Ich fand eine Lösung. Ich mache nur individuelle OAuthBearerAuthenticationProvider Anbieter und innerhalb dieser Klasse Im abrufen Token von Cookie und dann diese

public class MvcJwtAuthProvider : OAuthBearerAuthenticationProvider 
{ 
    public override Task RequestToken(OAuthRequestTokenContext context) 
    { 
     var token = context.Request.Cookies.SingleOrDefault(x => x.Key == "token").Value; 

     context.Token = token; 
     return base.RequestToken(context); 
    } 
} 

-context.Token

zuweisen und dann in startup.cs

public class Startup 
{ 
    public void Configuration(IAppBuilder app) 
    { 
     AutofacConfig.Configure(); 
     AreaRegistration.RegisterAllAreas(); 
     RouteConfig.RegisterRoutes(RouteTable.Routes); 
     FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 

     ConfigureOAuth(app); 
    } 

    public void ConfigureOAuth(IAppBuilder app) 
    { 
     var issuer = System.Configuration.ConfigurationManager.AppSettings["issuer"]; 
     var audience = System.Configuration.ConfigurationManager.AppSettings["appId"]; 
     var secret = TextEncodings.Base64Url.Decode(System.Configuration.ConfigurationManager.AppSettings["secret"]); 

     app.UseJwtBearerAuthentication(
      new JwtBearerAuthenticationOptions 
      { 
       AuthenticationMode = AuthenticationMode.Active, 
       AllowedAudiences = new[] { audience }, 
       IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[] 
       { 
        new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret) 
       }, 
       Provider = new MvcJwtAuthProvider() // override custom auth 

      }); 

    } 
} 
+0

In diesem schrecklichen _one-undoumened-MS-Auth-API-über-die-andere-mess_ Ihr Ansatz klingt vielversprechend. Danke für das Teilen! Ich vermisse nur einen Teil des Puzzles: Woher bekommst du '' '' loginService.GetToken''' oder wie sieht es aus? – Michael

+0

Ich habe eine weitere Antwort hinzugefügt, da es im Kommentarbereich schwierig sein könnte, diese Login-Service-Implementierung anzuzeigen. – TjDillashaw

0

@ Michael Dies ist, wie Login-Dienst aussieht mögen. Sein Aufruf zum Auth-Endpunkt

+0

Erstellen Sie keinen neuen HttpClient für jeden Anruf. Es soll wiederverwendet werden. Siehe [docs] (https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=netframework-4.7) –

+0

Danke. Ich weiß das. Aber dieses Projekt war nur zu Testzwecken. – TjDillashaw