我的方式非主流,控制却可以更加灵活,喜欢的朋友,不妨花一点时间学习一下

jwt认证分为两部分,第一部分是加密解密,第二部分是灵活的应用于中间件,我的处理方式是将获取token放到api的一个具体的controller中,将发放token与验证分离,token的失效时间,发证者,使用者等信息存放到config中。

1.配置:

在appsettings.json中增加配置

"jwt": {
"issuer": "issuer",//随意定义
"audience": "audience",//随意定义
"secretkey": "abc",//随意定义
"lifetime": 20, //单位分钟
"validatelifetime": true,//验证过期时间
"headfield": "useless", //头字段
"prefix": "prefix", //前缀
"ignoreurls": [ "/auth/gettoken" ]//忽略验证的url
}

2:定义配置类:

internal class jwtconfig
    {
        public string issuer { get; set; }
        public string audience { get; set; }

        /// <summary>
        /// 加密key
        /// </summary>
        public string secretkey { get; set; }
        /// <summary>
        /// 生命周期
        /// </summary>
        public int lifetime { get; set; }
        /// <summary>
        /// 是否验证生命周期
        /// </summary>
        public bool validatelifetime { get; set; }
        /// <summary>
        /// 验证头字段
        /// </summary>
        public string headfield { get; set; }
        /// <summary>
        /// jwt验证前缀
        /// </summary>
        public string prefix { get; set; }
        /// <summary>
        /// 忽略验证的url
        /// </summary>
        public list<string> ignoreurls { get; set; }
    }

3.加密解密接口:

 public interface ijwt
    {
        string gettoken(dictionary<string, string> clims);
        bool validatetoken(string token,out dictionary<string ,string> clims);
    }

4.加密解密的实现类:

 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>
        /// 获取到加密串
        /// </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>
        /// 生成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,//是否验证issuer
                    validateaudience = true,//是否验证audience
                    validatelifetime = this._jwtconfig.validatelifetime,//是否验证失效时间
                    validateissuersigningkey = true,//是否验证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.定义获取token的controller:

在startup.configureservices中注入 ijwt

 services.addtransient<ijwt, jwt>();//jwt注入 

[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.创建中间件:

 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.中间件暴露出去

 public static class useusejwtmiddlewareextensions
    {
        /// <summary>
        /// 权限检查
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        public static iapplicationbuilder usejwt(this iapplicationbuilder builder)
        {
            return builder.usemiddleware<usejwtmiddleware>();
        }
    }

8.在startup.configure中使用中间件:

 app.usejwt(); 

 

以1的配置为例:

除了请求 /auth/gettoken 不需要加头信息外,其他的请求一律要求头信息中必须带着 

userless:prefix (从auth/gettoken中获取到的token)