. Net core 2.0 jwt Identity Authentication System and jwt Identity Authentication System
After a long time,. net core 2.0 was finally released!
Core 1.1 has been used before. After upgrading 2.0, it is found that the authentication mechanism (Auth) has changed a lot. In 1.1, the authentication configuration is inConfigure completedIn 2.0, the authentication configuration is inConfigureServices.
Let's just talk about the code.
1. ConfigureServicesAuthentication configuration in
Var audienceConfig = Configuration. getSection ("Audience"); var response rickeyasbase64 = audienceConfig ["Secret"]; var keyByteArray = Encoding. ASCII. getBytes (Response rickeyasbase64); var signingKey = new response ricsecuritykey (keyByteArray); var tokenValidationParameters = new TokenValidationParameters {// The signing key must match! Keys = true, keys = signingKey, // Validate the JWT Issuer (iss) claim ValidateIssuer = true, ValidIssuer = audienceConfig ["Issuer"], // Validate the JWT Audience (aud) claim ValidateAudience = true, ValidAudience = audienceConfig ["Audience"], // Validate the token expiry ValidateLifetime = true, ClockSkew = TimeSpan. zero}; services. addAuthentication (options => {options. defaultAuthenticateScheme = JwtBearerDefaults. authenticationScheme; options. defaultChallengeScheme = JwtBearerDefaults. authenticationScheme ;}). addJwtBearer (o =>{// do not use https // o. requireHttpsMetadata = false; o. tokenValidationParameters = tokenValidationParameters ;});
Paste the content of etettings. json
"Audience": { "Secret": "Y2F0Y2yhciUyMHdvbmclMFWfsaZlJTIwLm5ldA==", "Issuer": "test", "Audience": "test" }
2.ConfigureUse authentication. Here I have reloaded the UseAuthentication method.
(1) first define a TokenProviderOptions class
Public class TokenProviderOptions {// <summary> // Request Path // </summary> public string Path {get; set ;}= "/Api/Token "; public string Issuer {get; set;} public string Audience {get; set ;} /// <summary> /// Expiration time /// </summary> public TimeSpan Expiration {get; set ;}= TimeSpan. fromMinutes (5000); public SigningCredentials {get; set ;}}
(2) define a TokenProviderExtensions class to overload the UseAuthentication Method
public static class TokenProviderExtensions { public static IApplicationBuilder UseAuthentication(this IApplicationBuilder app, TokenProviderOptions options) { if (app == null) { throw new ArgumentNullException(nameof(app)); } return app.UseMiddleware<TokenProviderMiddleware>(Options.Create(options)); } }
For the reason why UseAuthentication is long, you can refer
(3) write the AuthenticationMiddleware class to replace AuthenticationMiddleware.
Public class implements {private readonly RequestDelegate _ next; private readonly TokenProviderOptions _ options; private readonly IUserService _ service; public TokenProviderMiddleware (RequestDelegate next, IOptions <TokenProviderOptions> options, IUserService _ service, IAuthenticationSchemeProvider schemes) {_ next = next; _ options = options. value; this. _ service = _ service; Schemes = Schemes;} public IAuthenticationSchemeProvider Schemes {get; set ;} /// <summary> /// invoke the middleware /// </summary> /// <param name = "context"> </param> /// <returns> </returns> public async Task Invoke (HttpContext context) {// context. features. set <IAuthenticationFeature> (new AuthenticationFeature {OriginalPath = context. request. path, OriginalPathBase = context. request. pathBase}); // obtain the default S AuthenticationHandler var handlers = context. requestServices. getRequiredService <IAuthenticationHandlerProvider> (); foreach (var scheme in await Schemes. getRequestHandlerSchemesAsync () {var handler = await handlers. getHandlerAsync (context, scheme. name) as IAuthenticationRequestHandler; if (handler! = Null & await handler. HandleRequestAsync () {return ;}} var defaultAuthenticate = await Schemes. getdefaauthauthenticateschemeasync (); if (defaultAuthenticate! = Null) {var result = await context. AuthenticateAsync (defaultAuthenticate. Name); if (result ?. Principal! = Null) {context. User = result. Principal ;}// if (! Context. request. path. equals (_ options. path, StringComparison. ordinal) {await _ next (context); return;} // Request must be POST with Content-Type: application/x-www-form-urlencoded if (! Context. Request. Method. Equals ("POST") |! Context. request. hasFormContentType) {await ReturnBadRequest (context); return;} await GenerateAuthorizedResult (context );} /// <summary> /// verify the result and get the token /// </summary> /// <param name = "context"> </param> // <returns> </returns> private async Task GenerateAuthorizedResult (HttpContext context) {var username = context. request. form ["username"]; var password = context. request. form ["password"]; var identity = await GetIdentity (username, password); if (identity = null) {await ReturnBadRequest (context); return ;} // Serialize and return the response context. response. contentType = "application/json"; await context. response. writeAsync (GetJwt (username ));} /// <summary> /// verify the user /// </summary> /// <param name = "username"> </param> /// <param name = "password"> </param> // <returns> </returns> private Task <ClaimsIdentity> GetIdentity (string username, string password) {var isValidated = _ service. auth (username, password); if (isValidated) {return Task. fromResult (new ClaimsIdentity (new System. security. principal. genericIdentity (username, "Token"), new Claim [] {});} return Task. fromResult <ClaimsIdentity> (null) ;}/// <summary> // return the bad request (200) /// </summary> /// <param name = "context"> </param> /// <returns> </returns> private async Task ReturnBadRequest (HttpContext context) {context. response. status Code = 200; await context. response. writeAsync (JsonConvert. serializeObject (new {Status = false, Message = "authentication failed "}));} /// <summary> /// get the jwt // </summary> /// <param name = "username"> </param> /// <returns> </returns> private string GetJwt (string username) {var now = DateTime. utcNow; var claims = new Claim [] {new Claim (Response tregisteredclaimnames. sub, username), new Claim (fig. jti, Guid. newGuid (). toString (), new Claim (fig. iat, now. toUniversalTime (). toString (), ClaimValueTypes. integer64), // username new Claim (ClaimTypes. name, username), // role new Claim (ClaimTypes. role, "a")}; var jwt = new JwtSecurityToken (issuer: _ options. issuer, audience: _ options. audience, claims: claims, notBefore: now, expires: now. add (_ options. expiration), signingCredentials: _ options. signingCredentials); var encodedJwt = new JwtSecurityTokenHandler (). writeToken (jwt); var response = new {Status = true, access_token = encodedJwt, expires_in = (int) _ options. expiration. totalSeconds, token_type = "Bearer"}; return JsonConvert. serializeObject (response, new JsonSerializerSettings {Formatting = Formatting. indented });}}
(4) LastConfigureUse authentication in
var audienceConfig = Configuration.GetSection("Audience"); var symmetricKeyAsBase64 = audienceConfig["Secret"]; var keyByteArray = Encoding.ASCII.GetBytes(symmetricKeyAsBase64); var signingKey = new SymmetricSecurityKey(keyByteArray); var SigningCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256); app.UseAuthentication(new TokenProviderOptions { Audience = audienceConfig["Audience"], Issuer = audienceConfig["Issuer"], SigningCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256) });
3. Final Test