私人工具集7——webapi中的Token时效性验证

子曰:工欲善其事,必先利其器

github:https://github.com/redAntCpp/CSharpTools

紧接上篇,上篇只是实现了token的生成以及解析,顺便提到了验证机制。但是在实际业务中,通常需要对token进行时效性验证。就像去看电影,电影票当天有效,必须在有效期内进行使用,否则就需要重新买票。

token时效验证

总体思路

第一步中,有个代码:

 if (isAPIUser(UserName, PassWord))
                    {
                       //这里应该验证有效期,暂时没写,后续提供思路
                        return true;
                    }

这里应该加上时效验证。那么如何实现token的时效性验证呢,这里提供两个思路:

思路1

  1. 设置一个有效期,让客户端每次调用服务时,带上第一次获取token的时间戳(加密)。
  2. 服务端取到这个时间后,进行解密,然后加上有效期,对比当前服务器的时间,大于则有效,小于则失效,

在IsAuthorized加上这一段即可

string requestTime = httpContext.Request.Headers["rtime"]; //请求时间经过DESC签名,头文件
          if (string.IsNullOrEmpty(requestTime))return false;
            DateTime Requestdt = DateTime.Parse(Decrypt.RSADecrypt(PrivateKey,requestTime)).AddMinutes(int.Parse(TimeStamp));
            DateTime Newdt = DateTime.Now; //服务器接收请求的当前时间
            if (Requestdt < Newdt) //token已过期
            {
                ErrorMessage = "token已过期,请重新获取";
                return false;
           }

思路2

  1. 当客户端获取token时,服务端记录获取token的时间与用户。
  2. 每当客户使用服务进入验证环节时,取出步骤1中的时间与用户id,加上有效期。
  3. 判断加上有效期后的时间与服务器的时间大小。

两个思路的区别在于谁记录token时间,当然安全性肯定是思路2更安全。因为,如果客户不按要求进行传时间,那么服务端是无法验证的。但是思路2也有弊端,每次都记录用户的token,存储空间消耗大,而且查询速度也会影响token验证速度。如果存放在数据库上,连接数据库的网速也是个需要考虑的问题。
两种方法各有利弊。
现在分享一下本人的思路2的一个改进方法,使用sqlite来进行token的存储,关于sqlite参考:私人工具集5——C#数据库操作类(DBHelper)
sqlite可以存储在本地,不用考虑网络问题,且结构简单,体积小,非常适合这种记录日志。

实现
  1. 创建SQLite本地表,T_APIUser,用来记录用户信息,字段参考如下:
    在这里插入图片描述
  2. 创建本地表,T_TokenTrace,用来记录token生成时间以及状态。
    在这里插入图片描述
  3. 在过滤器中,修改判断逻辑,如果用户验证通过,那么就获取最后一次该用户获取token的时间,并加上有效期,与现在时间比较。
                    if (APIUserID != -1)
                    {
                        //验证有效期
                        string TokenCreateTime = getTokenCreateTime(APIUserID);
                        DateTime Requestdt = DateTime.Parse(TokenCreateTime).AddMinutes(int.Parse(TimeStamp));
                        if (Requestdt < DateTime.Now)
                        {
                            ErrorMessage = "token已过期,请重新获取";
                            return false;
                        }
                        else
                        {

                            return true;
                        }
                    }


  1. . 这里补充一下辅助方法:
 //辅助方法
        
        //验证账号密码
        private int isAPIUser(string UserNo, string PassWord)
        {
            Log.AddInfo("APIFilter.isAPIUser()", "Begin");
            string sqlstr = "SELECT APIUserID FROM T_APIUser where UserNo = @UserNo and PassWord = @PassWord";
            SQLiteParameter[] par = {
                new SQLiteParameter("@UserNo", UserNo),
                new SQLiteParameter("@PassWord",PassWord)
            };
            DataSet qry = site.SelectData(sqlstr, par);
            if (qry.Tables.Count == 1 && qry.Tables[0].Rows.Count == 0)
            {
                Log.AddError("APIFilter.isAPIUser()", "APIUser账号不存在");
                return -1;
            }
            else
            {
                Log.AddInfo("APIFilter.isAPIUser()", "End");
                return Convert.ToInt32(qry.Tables[0].Rows[0]["APIUserID"].ToString());
            }
        }

        private string getTokenCreateTime(int APIUserID)
        {
            string sqlStr = "SELECT CreateTime FROM T_TokenTrace where APIUserID = @APIUserID ORDER BY TokenTraceID  DESC LIMIT 1";
            SQLiteParameter[] par = {
                new SQLiteParameter("@APIUserID", APIUserID),
            };
            DataSet qry = site.SelectData(sqlStr, par);
            return qry.Tables[0].Rows[0]["CreateTime"].ToString();
        }

这样就可以简单实现token的有效期验证了。

实际演练
  1. 获取token接口
    在这里插入图片描述
  2. 在原来的token控制器中,加上一个测试用的接口,并加上我们的过滤器,程序会按顺序向下执行。
    在这里插入图片描述
  3. 设置有效期为2分钟。我这边读取的是json中的配置:
    在这里插入图片描述
  4. 验证token有效期内,接口是否能正常访问:
    在这里插入图片描述
  5. 2分钟后再次调用此接口:
    在这里插入图片描述

其他拓展

token一般每次都不一样,token的值跟加密的key相关,不同的key会产生不同的token。因此,如果想要每次获取的token都不一样,我们可以在配置key的时候,随机生成一个字符串作为key,用于保证token的随机性。要实现此功能,则不宜在配置文件中写入了,因为配置文件通常不进行修改。
在此就不再深入讨论。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值