每个新技术权限验证都有一套机制,之前项目webapi接口权限验证用的是owin做为权限验证,而.netcore权限限制使用的是identityserver4,采用jwt的方法验证token.

  • 首先使用guget包管理添加identityserver4包的引用,如图

  

  • 生成token方法
/// <summary>
        /// 生成token
        /// </summary>
        /// <param name="userid"></param>
        /// <param name="key">jwtkey</param>
        /// <returns></returns>
        public static string generatetoken(string userid, string key)
        {
            var tokenhandler = new jwtsecuritytokenhandler();
            var keybytes = system.text.encoding.default.getbytes(key);
            var authtime = datetime.utcnow;
            var expireaat = authtime.addhours(24);//token过期时间
            var timestamp = timestamp.generatetimestamp(authtime);//生成日间戳
            var sign = myunity.getmd5upper32((userid + "&" + timestamp + "&" + key).toupper());
            var tokendescriptor = new securitytokendescriptor()
            {
                subject = new claimsidentity(new claim[] {
                 new claim(jwtclaimtypes.audience,"api"),
                 new claim(jwtclaimtypes.issuer,"hengfeng"),
                 new claim(jwtclaimtypes.id,userid),
                 new claim("timestamp",timestamp),
                 new claim("sign",sign),
                   }),
                expires = expireaat,
                signingcredentials = new signingcredentials(new symmetricsecuritykey(keybytes),
                securityalgorithms.hmacsha256signature)
            };
            var token = tokenhandler.createtoken(tokendescriptor);
            var tokenstring = tokenhandler.writetoken(token);
            return tokenstring;
        }

 

   

  • 创建jwttokenfilter过滤器
 public class jwttokenfilter : actionfilterattribute
    {
        private readonly iconfiguration _config;
        public jwttokenfilter(iconfiguration configuration)
        {
            _config = configuration;
        }
        public override void onactionexecuting(actionexecutingcontext context)
        {
            try
            {
                var token = context.httpcontext.request.headers["token"];
                var tokenhandler = new jwtsecuritytokenhandler();
                var jwtsecuritytoken = tokenhandler.readjwttoken(token);
                var claims = jwtsecuritytoken.claims;
                var userid = claims.firstordefault(m => m.type == "id").value;
                var sign = claims.firstordefault(m => m.type == "sign").value;
                var expireaat = claims.firstordefault(m => m.type == "exp").value;
                var key = _config["jwt_key"];  
                var timestamp = claims.firstordefault(m => m.type == "timestamp").value;
                var sign_new = myunity.getmd5upper32((userid + "&" + timestamp + "&" + key).toupper());
                if (!sign_new.equals(sign, stringcomparison.invariantcultureignorecase))
                {
                    context.result = new jsonresult( "账号未登录");
                }
                else
                {
                    var expirestime = timestamp.convertintdatetime(expireaat);
                    if ((datetime.now - expirestime).minutes > 0)
                    {
                        context.result = new jsonresult("账号token失效");
                    }
                }
            }
            catch (exception ex)
            {
                context.result = new jsonresult(ex.tostring());
            }
        }
    }
  • 在使用控制器中添加 [servicefilter(typeof(jwttokenfilter))] 特性
     // get: api/default/5
        [httpget("{id}", name = "get")]
        [servicefilter(typeof(jwttokenfilter))]
        public string get(int id)
        {
            return "value";
        }
  • 如果该控制器不需要验证token,加上允许匿名访问特性即可
      [httppost]
        [allowanonymous]
        public void post([frombody] string value)
        {

        }

  最后:注意登录成功后,需要把生成的token返回给前端,前端再一次请求系统其它需要验证token的接口中,在head中加上token值。

 

用到的加密算法

  /// <summary>
       /// md5 16位长度
       /// </summary>
       /// <param name="svalue"></param>
       /// <returns></returns>
        public static string getmd5upper16(string svalue)  
        {
            md5cryptoserviceprovider md5 = new md5cryptoserviceprovider();
            string s = bitconverter.tostring(md5.computehash(utf8encoding.default.getbytes(svalue)), 4, 8);
            s = s.replace("-", "").toupper();
            return s;
        }
        /// <summary>
        ///  md5 32位长度
        /// </summary>
        /// <param name="svalue"></param>
        /// <returns></returns>
        public static string getmd5upper32(string svalue)  
        {
            md5cryptoserviceprovider md5 = new md5cryptoserviceprovider();
            string s = bitconverter.tostring(md5.computehash(utf8encoding.default.getbytes(svalue)));
            s = s.replace("-", "").toupper();
            return s;
        }