. net core webapi jwt more refreshing authentication

Keywords: PHP JSON encoding

Original text: . net core webapi jwt more refreshing authentication

My way is not mainstream, but I can control it more flexibly. My favorite friend may as well take a moment to learn

jwt authentication is divided into two parts. The first part is encryption and decryption. The second part is flexible application to middleware. My processing method is to put the obtained token into a specific controller of the api, separate the issued token from the verification, and store the information such as the expiration time of the token, the issuer and the user in config.

1. configuration:

Add configuration in appsettings.json

"Jwt": {
"Issuer": "issuer",//Random definition
"Audience": "Audience",//Random definition
"SecretKey": "abc",//Random definition
"Lifetime": 20, //Unit minute
"ValidateLifetime": true,//Validation expiration time
"HeadField": "useless", //Header field
"Prefix": "prefix", //prefix
"IgnoreUrls": [ "/Auth/GetToken" ]//Ignore authenticated url
}

2: define configuration class:

internal class JwtConfig
    {
        public string Issuer { get; set; }
        public string Audience { get; set; }

        /// <summary>
        //Encryption key
        /// </summary>
        public string SecretKey { get; set; }
        /// <summary>
        ///Life cycle
        /// </summary>
        public int Lifetime { get; set; }
        /// <summary>
        ///Verify lifecycle or not
        /// </summary>
        public bool ValidateLifetime { get; set; }
        /// <summary>
        ///Validation header field
        /// </summary>
        public string HeadField { get; set; }
        /// <summary>
        ///jwt validation prefix
        /// </summary>
        public string Prefix { get; set; }
        /// <summary>
        ///Ignore authenticated url
        /// </summary>
        public List<string> IgnoreUrls { get; set; }
    }

3. Encryption and decryption interface:

 public interface IJwt
    {
        string GetToken(Dictionary<string, string> Clims);
        bool ValidateToken(string Token,out Dictionary<string ,string> Clims);
    }

4. Implementation class of encryption and decryption:

 install-package System.IdentityModel.Tokens.Jwt 

 public class Jwt : IJwt
    {
        private IConfiguration _configuration;
        private string _base64Secret;
        private JwtConfig _jwtConfig = new JwtConfig();
        public Jwt(IConfiguration configration)
        {
            this._configuration = configration;
            configration.GetSection("Jwt").Bind(_jwtConfig);
            GetSecret();
        }
        /// <summary>
        /// Get encrypted string
        /// </summary>
        private void GetSecret()
        {
            var encoding = new System.Text.ASCIIEncoding();
            byte[] keyByte = encoding.GetBytes("salt");
            byte[] messageBytes = encoding.GetBytes(this._jwtConfig.SecretKey);
            using (var hmacsha256 = new HMACSHA256(keyByte))
            {
                byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
                this._base64Secret= Convert.ToBase64String(hashmessage);
            }
        }
        /// <summary>
        /// generate Token
        /// </summary>
        /// <param name="Claims"></param>
        /// <returns></returns>
        public string GetToken(Dictionary<string, string> Claims)
        {
            List<Claim> claimsAll = new List<Claim>();
            foreach (var item in Claims)
            {
                claimsAll.Add(new Claim(item.Key, item.Value));
            }
            var symmetricKey = Convert.FromBase64String(this._base64Secret);
            var tokenHandler = new JwtSecurityTokenHandler();
            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Issuer = _jwtConfig.Issuer,
                Audience = _jwtConfig.Audience,
                Subject = new ClaimsIdentity(claimsAll),
                NotBefore = DateTime.Now,
                Expires = DateTime.Now.AddMinutes(this._jwtConfig.Lifetime),
                SigningCredentials =new SigningCredentials(new SymmetricSecurityKey(symmetricKey),
                                           SecurityAlgorithms.HmacSha256Signature)
            };
            var securityToken = tokenHandler.CreateToken(tokenDescriptor);
            return tokenHandler.WriteToken(securityToken);
        }
        public bool ValidateToken(string Token, out Dictionary<string, string> Clims)
        {
            Clims = new Dictionary<string, string>();
            ClaimsPrincipal principal = null;
            if (string.IsNullOrWhiteSpace(Token))
            {
                return false;
            }
            var handler = new JwtSecurityTokenHandler();
            try
            {
                var jwt = handler.ReadJwtToken(Token);

                if (jwt == null)
                {
                    return false;
                }
                var secretBytes = Convert.FromBase64String(this._base64Secret);
                var validationParameters = new TokenValidationParameters
                {
                    RequireExpirationTime = true,
                    IssuerSigningKey = new SymmetricSecurityKey(secretBytes),
                    ClockSkew = TimeSpan.Zero,
                    ValidateIssuer = true,//Is it verified? Issuer
                    ValidateAudience = true,//Is it verified? Audience
                    ValidateLifetime = this._jwtConfig.ValidateLifetime,//Whether to verify the failure time
                    ValidateIssuerSigningKey = true,//Is it verified? SecurityKey
                    ValidAudience = this._jwtConfig.Audience,
                    ValidIssuer = this._jwtConfig.Issuer
                };
                SecurityToken securityToken;
                principal = handler.ValidateToken(Token, validationParameters, out securityToken);
                foreach (var item in principal.Claims)
                {
                    Clims.Add(item.Type, item.Value);
                }
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }
    }

5. Define the Controller to get Token:

Inject IJwt in Startup.ConfigureServices

Services. Addtransient < ijwt, JWT > (); / / JWT injection

[Route("[controller]/[action]")]
    [ApiController]
    public class AuthController : ControllerBase
    {
        private IJwt _jwt;
        public AuthController(IJwt jwt)
        {
            this._jwt = jwt;
        }
        /// <summary>
        /// getToken
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public IActionResult GetToken()
        {
            if (true)
            {
                Dictionary<string, string> clims = new Dictionary<string, string>();
                clims.Add("userName", userName);
                return new JsonResult(this._jwt.GetToken(clims));
            }
        }
    }

6. Create middleware:

 public class UseJwtMiddleware
    {
        private readonly RequestDelegate _next;
        private JwtConfig _jwtConfig =new JwtConfig();
        private IJwt _jwt;
        public UseJwtMiddleware(RequestDelegate next, IConfiguration configration,IJwt jwt)
        {
            _next = next;
            this._jwt = jwt;
            configration.GetSection("Jwt").Bind(_jwtConfig);
        }
        public Task InvokeAsync(HttpContext context)
        {
            if (_jwtConfig.IgnoreUrls.Contains(context.Request.Path))
            {
                return this._next(context);
            }
            else
            {
                if (context.Request.Headers.TryGetValue(this._jwtConfig.HeadField, out Microsoft.Extensions.Primitives.StringValues authValue))
                {
                    var authstr = authValue.ToString();
                    if (this._jwtConfig.Prefix.Length > 0)
                    {
                        authstr = authValue.ToString().Substring(this._jwtConfig.Prefix.Length+1, authValue.ToString().Length -(this._jwtConfig.Prefix.Length+1));
                    }
                    if (this._jwt.ValidateToken(authstr, out Dictionary<string, string> Clims))
                    {
                        foreach (var item in Clims)
                        {
                            context.Items.Add(item.Key, item.Value);
                        }
                        return this._next(context);
                    }
                    else
                    {
                        context.Response.StatusCode = 401;
                        context.Response.ContentType = "application/json";
                        return context.Response.WriteAsync("{\"status\":401,\"statusMsg\":\"auth vaild fail\"}");
                    }
                }
                else
                {
                    context.Response.StatusCode = 401;
                    context.Response.ContentType = "application/json";
                    return context.Response.WriteAsync("{\"status\":401,\"statusMsg\":\"auth vaild fail\"}");
                }
            }
        }
    }

7. Middleware exposed

 public static class UseUseJwtMiddlewareExtensions
    {
        /// <summary>
        ///Authority check
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        public static IApplicationBuilder UseJwt(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<UseJwtMiddleware>();
        }
    }

8. Use middleware in Startup.Configure:

 app.UseJwt(); 

 

Take the configuration of 1 as an example:

In addition to the request / auth/getToken, no additional header information is required. All other requests must be accompanied by

userless:prefix (token obtained from Auth/GetToken)

Posted by syn1234 on Mon, 04 Nov 2019 13:41:55 -0800