使用JWT进行登录认证的一些问题

正在使用SPA+Restful API开发一个网站,对于需要进行登录认证,遂采用JWT的token方式。

根据JWT的流程,当用户使用用户名密码登录成功后,服务端会生成一个唯一的token返回给客户端,客户端存储在Cookie或者Storage中,用户在以后的请求中都带上这个token,服务器进行token的合法性验证,是否已过期等等,从而返回不同的结果。
但有几点疑惑:
1、当用户注销时(并为到达过期时间),该如何处理?删除本地存储的token?
2、如何延续token的有效性,当一个用户登录后,并长时间操作,这个时间超过了token的expires,难道告诉用户再登录一次,显然不行。在每次请求中都检测token的过期时间,在将要过期的时候(小于1分钟)更新token?那恰好错过了这一分钟怎么办?在每一次的请求后,都对token进行更新,返回客户端吗?那服务端将不停的计算操作和客户端将不停的存储操作。该如何处理?
这个问题在https://segmentfault.com/q/1010000003692779已提出,但并没有得到很好的回答,遂再提一次。

阅读 26.8k
3 个回答

我的做法是这样的:

  1. 在拦截器中每次校验token的过期时间,如果token快要过期(设置一个合理的时间,防止页面多个ajax请求导致现有token过期,比如三分钟。此处我个人猜测跟微信的那个token类似,就是每次你获取新的token后,旧的的token还有一定的缓冲期),则颁发新的token。

  2. 前端我这边用的angularJs,前端http拦截器中获取每次检测是否颁发了新的token,如果颁发了的话,则替换旧的。

检测token时间过期比较简单,后端代码就不放了
前端代码如下:

.factory('authInterceptor', function($q, $rootScope, userService) {
    return {
        request : function(config) {
            config.headers = config.headers || {};
            //设置认证token
            config.headers.Authorization = userService.getCode();

            return config;
        },

        response : function(response) {
            if(response.status == 401 || (response.data && response.data.code == 401)) {
                $rootScope.$emit('userIntercepted', 'notLogin', response);
                return;
            }
            
            //检测到新的token,则替换新的token
            if(response.headers('token')) {
                userService.putCode(response.headers('token'));
            }

            return response;
        },

        responseError : function(rejection) {
            if(rejection.status == 401 || (rejection.data && rejection.data.code == 401)) {
                $rootScope.$emit('userIntercepted', 'notLogin', rejection);
                return;
            }

            return $q.reject(rejection);
        }
    }
})
  1. 未过期,用户退出登陆,一般就是清除cookie。大部分时候都是这么做的。

  2. 如果你设定了一个cookie有效时长为T,而且一定要从用户的最后一次操作算起,如果T长的时间没有操作,就过期。如果是这样的需求的话,就只能在每个用户动作在服务器上重新更新cookie有效期。 别无他法。

你这个问题是很疑惑,但是通常很少遇到。 因为时间是多长呢。 如果有效期是N天的那种,这个问题就很少出现了。 如果是30分钟之类的短有效期,又为何不考虑使用会话级别的呢。 关闭浏览器时失效,不关闭就不失效的方式。

  1. 删除token,具体而言就是cookie或者local storage

  2. 提供三个思路供参考:

    1. 每次合法的访问延长token有效期,也就是每次下发新token,但这样解决不了这个场景:从第一次登录的大约T天内有效

    2. 如果是天级别的token,将失效时间设置到凌晨,可以在很大程度上避免用户操作时token失效的情形

    3. 复杂一点的,如果某次请求中token快要到期,才更新token,延长的时间大致能允许用户完成这次操作

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏