当前位置: 移动技术网 > IT编程>开发语言>.net > .net core webapi jwt 更为清爽的认证 ,续期很简单(2)

.net core webapi jwt 更为清爽的认证 ,续期很简单(2)

2019年05月28日  | 移动技术网IT编程  | 我要评论

释来果,回到古代去逍遥,苏州oa

.net core webapi jwt 更为清爽的认证  后续:续期以及设置token过期

续期: 续期的操作是在中间件中进行的,续期本身包括了前一个token的过期加发放新的token,所以在说续期前先说token过期

在开始之前先增加相应的配置:续期间隔 和 续期携带给前端的新token的head.jwtconfig同步修改

 "jwt": {
    "issuer": "issuer",
    "audience": "audience",
    "secretkey": "abc",
    "lifetime": 20, //单位分钟
    "renewaltime": 10, //单位分钟,token续期的时间间隔,10表示超过10分钟再次请求就续期
    "validatelifetime": true,
    "headfield": "auth", //头字段
    "retokenheadfield": "retoken",
    "prefix": "", //前缀
    "ignoreurls": [ "/swagger/", "/swagger/v1/swagger.json", "/auth/gettoken", "/auth/invalidatetoken" ]
  }
 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 int renewaltime { get; set; }
        /// <summary>
        /// 是否验证生命周期
        /// </summary>
        public bool validatelifetime { get; set; }
        /// <summary>
        /// 验证头字段
        /// </summary>
        public string headfield { get; set; }
        /// <summary>
        /// 新token的head字段
        /// </summary>
        public string retokenheadfield { get; set; }
        /// <summary>
        /// jwt验证前缀
        /// </summary>
        public string prefix { get; set; }
        /// <summary>
        /// 忽略验证的url
        /// </summary>
        public list<string> ignoreurls { get; set; }
    }

 

1.设置token过期

首先在jwt.cs中增加静态属性 

public static list<string> invalidatetokens = new list<string>();

然后添加 jwt中添加方法:

bool invalidatetoken(string token);
public bool invalidatetoken(string token)
        {
            if (!invalidatetokens.contains(token))
            {
                invalidatetokens.add(token);
            }
            return true;
        }

修改jwt中gettoken的方法:

string gettoken(idictionary<string, string> clims,string oldtoken=null);
  public string gettoken(idictionary<string, string> claims,string oldtoken=null)
        {
            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);
            if (!string.isnullorempty(oldtoken))//执行旧token过期
            {
                if (!invalidatetokens.contains(oldtoken))
                {
                    invalidatetokens.add(oldtoken);
                }
            }
            return tokenhandler.writetoken(securitytoken);
        }

修改: validatetoken

  public bool validatetoken(string token, out dictionary<string, string> clims)
        {
            clims = new dictionary<string, string>();
            if (invalidatetokens.contains(token))
            {
                return false;
            }
            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)
            {
                console.writeline(ex.tostring());
                return false;
            }
        }

 

紧接着在auth中增加接口

/// <summary>
        /// 强制token失效
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        [httppost]
        public iactionresult invalidatetoken(string token)
        {
            return new jsonresult(this._jwt.invalidatetoken(token));
        }

//需要让当前token强制过期的时候,客户端调用 invalidatetoken 传入当前token就可以

2.续期:修改中间件:usejwtmiddleware

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)&&!jwt.invalidatetokens.contains(authstr))
                    {
                        list<string> climskeys = new list<string>() { "nbf", "exp", "iat", "iss","aud" };
                        idictionary<string, string> renewaldic = new dictionary<string, string>();
                        foreach (var item in clims)
                        {
                            if (climskeys.firstordefault(o=>o==item.key) == null)
                            {
                                context.items.add(item.key, item.value);
                                renewaldic.add(item.key, item.value);
                            }
                        }
                        //验证通过的情况下判断续期时间
                        if (clims.keys.firstordefault(o => o == "exp") != null)
                        {
                            var start = new datetime(1970, 1, 1, 0, 0, 0, datetimekind.utc);
                            var timespan = long.parse(clims["exp"]);
                            var expdate = start.addseconds(timespan).tolocaltime();
                            var o = expdate - datetime.now;
                            if (o.totalminutes < _jwtconfig.renewaltime)
                            {
                                //执行续期当前token立马失效
                                //var newtoken = this._jwt.gettoken(renewaldic, authstr);
                   //var newtoken=this._jwt.gettoken(renewaldic);//生成新token当前token仍可用,过期时间以lifetime设置为准 context.response.headers.add(_jwtconfig.retokenheadfield, newtoken); } } 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\"}"); } } } }

本例中,当客户端获取token超过10分钟未超过20分钟的这个时间段如果再执行请求,那么服务端就会给head头上带上 retoken:newtoken

下次请求带着新token过来就可以

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网