前端设计之——双token设计

为什么要使用双token

token是为了防止用户信息传来传去导致被劫持,但是假如token没有过期时间或者过期很长,那么显然token被劫持还是不安全的,token就失去了意义。

如果token过期时间设置的过短,这时就需要用户频繁的进行登录操作,对于用户体验不好

这时就需要双token来达到无痛刷新token的效果

具体实现:

设计图

具体逻辑

  • 当用户登录成功后,后端会返回两个token,一个accessToken过期时间可能十分钟或二十分钟就会过期,一个是refreshToken过期时间有一周或两周时间
  • 用户登录成功之后的请求,我会在axios的请求拦截器中将accessToken带到请求头中,如果accessToken没有过期就是正常的发送请求,一旦用户发送请求时accessToken过期了,后端会返回相应状态码‘401’
  • 此时我们会在响应拦截器中拦截到这个‘401’状态码,这也就表示这accessToken过期了,这时我需要把请求头换成refreshToken,再次发送这个请求,去获取更新后的accessToken
  • 此时会有两种情况,一个是refreshToken没过期,一个是refreshToken也过期了
  • 如果refreshToken没过期,后端会返回响应状态码1024并返回更新后的accessToken,这时也会被响应拦截器拦截到,这时我就需要把更新后的accessToken带到请求头上再次发送这个请求,此时accessToken肯定没过期,请求正常发送
  • 如果refreshToken过期了,后端会返回响应状态码1023,这时我就知道refreshToken也过期了,也就是用户登录过期了,就会让用户重新进行登录操作

自此就完成了token的无痛刷新,在用户访问网站时,用户对于accessToken的刷新是没有体感的,只会在一两周的时间间隔refreshToken也过期的时候进行一次登录操作,就可以正常访问网站了,即降低了用户实际accessToken被劫持的风险,又提升了用户的体验

实现代码:

let refreshToken = getToken('refreshToken') || ''
let isrefreshToken = false
if (!getToken('refreshToken')) {
    isrefreshToken = false
    if (!getToken('refreshToken')) {
        isrefreshToken = true
    }
}

// 添加请求拦截器
request.interceptors.request.use((config) => {
    // 在请求之前做些什么(获取并设置token)
    // 对双token的操作


    let token = getToken('accessToken')
    // 如果有token
    if (token) {
        // 并且token没过期
        if (!isrefreshToken) {
            config.headers['x-token'] = getToken('accessToken') || ''
        }
    }

    // 如果有refreshToken
    if (refreshToken) {
        // 且需要刷新token
        if (isrefreshToken) {
            config.headers['x-token'] = getToken('refreshToken')
        }
    }
    return config
}),
    (error) => {
        return Promise.reject(error)
    }

// 添加响应拦截器
request.interceptors.response.use((response) => {
    // 对响应数据做些什么
    console.log('响应状态码', response.data.code)
    // console.log('isrefreshToken', isrefreshToken);

    let code = response.data.code

    // 还没有设置refreshToken请求头,需要设置一下再次发送请求
    if (!refreshToken && getToken('refreshToken') != null) {
        refreshToken = getToken('refreshToken')
        return request(response.config)
    }

    if (code == 401) {
        //accessToken过期了,需要带着refreshToken,去换取新的token
        refreshToken = getToken('refreshToken')
        isrefreshToken = true
        // 相当于重新走一遍刚刚的请求
        return request(response.config)
    }

    if (code == 1024) {
        setToken('accessToken', response.data.data)
        isrefreshToken = false
        return request(response.config)
    } else if (code == 1023) {
        // 将本地token删除
        removeToken('refreshToken')
        removeToken('accessToken')
        // 跳转到登录页面,重新登录
        router.push('/login')
        //返回信息,让用户重新登录
        isrefreshToken = true
        alert('登录已超期,请重新登录')
    }

    return response
}),
    (error) => {
        return Promise.reject(error)
    }

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在使用WebSocket进行通信时,我们通常需要对连接进行验证和授权,以确保只有经过身份验证的用户才能访问WebSocket。本文将介绍如何使用Token验证并将WebSocket的clientId绑定到用户的uid(微信)上实现WebSocket通信。 1. Token验证 在使用WebSocket建立连接时,可以在请求头中携带Token进行验证。我们可以在后端实现一个Token验证的过滤器,用于验证请求头中的Token是否有效。如果Token无效,则返回错误信息并关闭WebSocket连接;如果Token有效,则允许WebSocket连接。 以下是一个Token验证的Java代码示例: ```java public class TokenFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; String token = req.getHeader("token"); // 从请求头中获取Token if (token == null) { // 如果Token为空,返回错误信息并关闭WebSocket连接 HttpServletResponse resp = (HttpServletResponse) response; resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Token is required"); return; } // 验证Token是否有效,验证通过则允许WebSocket连接,否则返回错误信息并关闭WebSocket连接 if (validateToken(token)) { chain.doFilter(request, response); } else { HttpServletResponse resp = (HttpServletResponse) response; resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid token"); } } private boolean validateToken(String token) { // Token验证逻辑 return true; // 如果Token有效,则返回true,否则返回false } } ``` 在使用WebSocket时,我们需要在WebSocket请求中添加Token头信息,如下所示: ```javascript const ws = new WebSocket("ws://localhost:8080/websocket"); ws.onopen = function(event) { ws.send("Hello WebSocket"); // 发送消息 }; ws.setRequestHeader("token", "your_token"); // 添加Token头信息 ``` 2. clientId绑定到uid上 在WebSocket连接建立时,我们可以将WebSocket的clientId与用户的uid进行绑定,以便后续使用时能够快速找到对应的用户。在这里,我们以微信用户的openid作为用户的uid进行绑定。 在后端,我们可以维护一个WebSocket连接管理器,用于管理WebSocket连接和用户的绑定关系。当WebSocket连接建立时,我们可以将clientId和openid进行绑定,并将绑定关系保存到连接管理器中。 以下是一个WebSocket连接管理器的Java代码示例: ```java public class WebSocketManager { private static final Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>(); private static final Map<String, String> clientIdToOpenid = new ConcurrentHashMap<>(); public static void addSession(String clientId, WebSocketSession session) { sessions.put(clientId, session); } public static void removeSession(String clientId) { sessions.remove(clientId); clientIdToOpenid.remove(clientId); } public static void bindClientIdToOpenid(String clientId, String openid) { clientIdToOpenid.put(clientId, openid); } public static String getOpenidByClientId(String clientId) { return clientIdToOpenid.get(clientId); } public static WebSocketSession getSessionByClientId(String clientId) { return sessions.get(clientId); } } ``` 当WebSocket连接建立时,我们可以在WebSocket处理器中获取openid,并将clientId和openid进行绑定,如下所示: ```java @Component public class WebSocketHandler extends TextWebSocketHandler { @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { String clientId = session.getId(); // 获取WebSocket的clientId String openid = getOpenidFromSession(session); // 获取用户的openid WebSocketManager.addSession(clientId, session); // 将WebSocket连接添加到连接管理器中 WebSocketManager.bindClientIdToOpenid(clientId, openid); // 将clientId和openid进行绑定 } private String getOpenidFromSession(WebSocketSession session) { // 从WebSocket的Attributes中获取用户的openid return (String) session.getAttributes().get("openid"); } } ``` 在后续使用WebSocket时,我们可以根据用户的openid快速找到对应的WebSocket连接,如下所示: ```java String openid = "your_openid"; String clientId = WebSocketManager.getClientIdByOpenid(openid); WebSocketSession session = WebSocketManager.getSessionByClientId(clientId); if (session != null && session.isOpen()) { session.sendMessage(new TextMessage("Hello WebSocket")); } ``` 以上就是使用Token验证并将WebSocket的clientId绑定到用户的uid上实现WebSocket通信的方法。通过Token验证,我们可以确保WebSocket连接的安全性;通过将clientId和openid进行绑定,我们可以快速找到对应的WebSocket连接,提高通信的效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值