token过期时web前端如何自动刷新token

以token处理登录的web系统,一般会有两个token:access-token和refresh-token。

node.js中,一般用jsonwebtoken这个模块。

access-token,是用户输入登录的账号密码,后台去db验证然后颁发的,它一般记录在浏览器的cookie中,并在浏览器关闭时自动删除,页面访问或ajax访问会自动通过cookie传回到后台,后台直接内存中校验,不用访问db,所以效率高;为了在access-token泄漏后及时止损,一般access-token会设置一个有效期,如1-8小时。

access-token设置了有效期后,过期了怎么办?为了及时止损,有效期不能设置太长,过期是一定会遇到的,比如工作狂,如果有效期设置的是8小时,他开着浏览器工作12小时,费力断断续续花了1个小时(电话多,喝咖啡尿多)打了张订单,提交时token过期了。再比如某些大屏幕展示的页面,可能连续几天几月的开着。遇到过期怎么办?

  1. 重定向到登录页面,用户输入账号密码登录后,再自动跳回订单页面,之前的资料都丢了,用户骂一句“靠”忍气吞声重新打。如果每天遇到一次,可能还可以忍。如果有效期太短,如1小时,每天遇到5,6次,那用户可能不干了,这时你可能要把未提交的订单资料暂时存到localstorage里面。
  2. 弹出登录框。登录框内容和代码如何做,预先就加载了,每个页面都有这部分,感觉很浪费,因为大部分时间用不上,动态从后台加载,可能不好实现。
  3. 登录后把账号密码记录在浏览器中,自动登录。但基于安全考虑,一般是用户特别勾选“记住我”,才会加密记录账号密码到localstorage中,用户下次打开浏览器时自动登录。如果token过期就自动登录,如何及时止损?后台修改密码或禁用账号,如何同步到前端的localstorage中。大部分app是这么干的。以上3种都是要再次去后台数据库验证,所以token过期时间不能太短,否则效率很差。
  4. 设置refresh-token机制,颁发access-token时同时颁发一个refresh-token,唯一区别是refresh-token有效期比较长,比如1个月。当access-token过期后,拿着refresh-token到后台换取新的access-token。通过在后台为refresh-token设置黑名单来及时止损,所以有黑名单的时候,可能效率也会一样的差。refresh-token也过期后,那就只有老老实实的让用户输入账号密码登录了,就是前面的1,2方法。因为refresh-token不常用,所以最好不要放在cookie中避免每次自动传到后台,放在localstorage较好。

刷新access-token过程,如何让用户没感觉?思路是:发现access-token,自动用refresh-token去刷新,然后再自动跳到原来页面或者自动调用一次原来的ajax。

  1. web页面访问时,nodejs后台中间件拦截到access-token过期,返回一个html,里面包含刷新token和跳转:
    
    
    
    
    
    
    
    
    

     

  2. ajax调用时,封装一下jquery的ajax:
    yjClient.ajax=function(options){
        var data=options.data;
    	var url=options.url;
    
    	function callAjax(){
        	$.ajax({
        		cache:options.cache?options.cache:false,
        		method:options.method?options.method:(options.type?options.type:'get'),
        		async:(options.async==undefined)?true:options.async,
        		url:url,
            	data:data,
            	success:function(data, textStatus){
        			if (options.success){
        				options.success(data);
        			}				
        		},
        		error:function(XMLHttpRequest, textStatus, errorThrown){
        		    if (XMLHttpRequest.responseText){
        		        var msg=XMLHttpRequest.responseText;
        		        var err=JSON.parse(XMLHttpRequest.responseText);
        		    }
        		    else{
        		        var msg=yjClient.getAjaxErrorMsg(XMLHttpRequest,textStatus,errorThrown);
        		        var err=new Error(msg);
        		    }
        		    if (err.code=="tm.err.foil.accessTokenExpired"){
        		        console.log('refresh token...');
        		        var refresh_Token=refresh_token=localStorage.getItem(yjClient.cookieIDs.refreshToken);
        		        $.ajax({
        		            cache:false,
        		            method:"get",
        		            async:true,
        		            url:'/app/account/refreshToken',
        		            data:{
        		                refresh_token:refresh_token
        		            },
        		            success:function(data, textStatus){
        		                callAjax();
        		            },
        		            error:function(XMLHttpRequest, textStatus, errorThrown){
        		                //access-token刷新失败(可能refresh-token过期或者账号密码改了),重定向到登录页面
        		                yjClient.redirectToLoginPage();
        		            }
        		        });
        		        return;
    				}
    				if (err.code=="tm.err.foil.tokenNotProvided"){
    					yjClient.redirectToLoginPage();
    					return;
    				}
        			if (options.error){
        				options.error(err);
        			}
        			else{
        				yjClient.showDialog(yjDD["Failed!"],msg);
        			}
        		}
        	});
        }
    	callAjax();
    }

     

你可能感兴趣的:(Javascript,Node.js)