模仿某B长期登录有效之双Token机制

模仿某B长期登录有效之双Token机制

提示:需要有一定了解token机制的同学进行学习



对于某B如何长时间处于登录状态发起思考

大家应该都有用过某B吧,不知道使用某B的同学有没有发现一个问题,别人的网站,登录过后,一段时间不使用就自动退出了,而某B,就算你长时间不使用还是处于登录状态。并且所有的网站也都是你用多久就是多久,不会出现你用到一半就突然退出的情况。那么对于这种情况,本人对此做出了深深的思考,偷偷的查询了资料过后,发现大伙提到了一种名叫双token的东西。
在我简单的demo使用过后呢,发现,确实不错。本文思路有借鉴都绝无抄袭,大部分想法和处理都为自己独立思考而成。不喜勿喷。谢谢。


提示:以下案例可供参考

一、何为双Token?

顾名思义:两个token,在基础idToken之上,添加一个新的refreshToken,
在jwt的官网解释为:Refresh Tokens

二、使用步骤

1.实现思路

思路真的非常非常的重要,get不到双token的那个点,就会想不通这和普通的单token的区别在哪里,本文仅展示自己对于jwt工具双token的处理方式,如有雷同,纯属巧合。
在登录请求后发放双token返回给前端,原因:主要进行认证的token其实还是idToken,只有在短期token过期时,jwt工具对token进行解析失败的情况下,才会进行对refreshToken进行处理,在实际上,refreshToken与idToken在生产时的参数可以是相同的,也可以是不同的,具体逻辑具体分析即可。
双token传输到后端后,会先校验idToken,idToken如果没有过期直接成功登录,不会去刷新token令牌(这里也可以选择刷新,我觉得是没有必要的),
如果idToken过期,那么在解析时就会出现超时异常,捕获异常继续解析refreshToken即可,如若refreshToken也出现超时异常,则拦截器进行拦截,让用户进行重新登录即可。在这里可对token异常单独做出处理。如果refreshToken持续有效的情况下,则操作成功,并让前端请求token刷新接口即可。
这时可能会出现,前一秒refreshToken未过期,但请求刷新接口时过期的可能性,那么此时jwt解析body用户信息时也会出现超时异常,此时接口直接返回相应跳转code或者直接进行页面跳转即可。系统无法再为用户刷新token,只能让用户重新登录。

拦截器处理代码(示例):

以下shortToken代表idToken,longToken代表refrshToken

@Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
        if (!(object instanceof HandlerMethod)) {
            return true;
        }
        String shortToken = request.getHeader("authorization");// 从 http 请求头中取出 token
        String longToken = request.getHeader("authorization-long");
        log.info("短期token:{}", shortToken);
        log.info("长期token:{}", longToken);
        // 执行认证
        if (null == shortToken && null == longToken) {
            throw new RuntimeException("无token,请重新登录");
        }
        String phone = null;
        Claims shortTokenClaim = null;
        Claims longTokenClaim = null;
        if (null != shortToken) {
            try {
                // 先验证短期token
                shortTokenClaim = tokenObj.getTokenClaim(shortToken);
                phone = shortTokenClaim.getSubject();
                if (null == phone) {
                    throw new RuntimeException("用户不存在,请重新登录");
                }
                log.info("通过短期token登录成功");
                return true;
            } catch (Exception j) {
                log.debug("短期token过期,继续检测长期token");
            }
        }

        try {
            log.info("检查长期令牌加长期令牌时间");
            longTokenClaim = tokenObj.getTokenClaim(longToken);
            phone = longTokenClaim.getSubject();
            if (null == phone) {
                throw new RuntimeException("用户不存在,请重新登录");
            }
            log.info("通过长期token登录成功,需要刷新token");
        } catch (Exception e) {
            log.error("长期令牌已失效请重新登录");
            return false;
        }
        return true;
    }

工具类(示例):

package com.mrone.util;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class JwtUtil {

    private String secret= "NjYwQ0Y0N0M3ODhFODYwOUU2RDM1RTNDRkNENjQ1REE=";
    private long expire= 3600;
    private String header="token";
    public String getLongTimeToken (String phone){
        Date nowDate = new Date();
        //过期时间  两天后的这个点
        Date expireDate = new Date(nowDate.getTime() + expire * 1000 * 47);
        return Jwts.builder()
                .setHeaderParam("typ", "JWT")
                .setSubject(phone)
                .setIssuedAt(nowDate)
                .setExpiration(expireDate)
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();
    }
    //一分钟后过期
    public String getShortTimeToken (String phone){
        Date nowDate = new Date();
        Date expireDate = new Date(nowDate.getTime() + expire*100 );
        return Jwts.builder()
                .setHeaderParam("typ", "JWT")
                .setSubject(phone)
                .setIssuedAt(nowDate)
                .setExpiration(expireDate)
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();
    }
	//刷新Token
    public Map refresh(String auth){
        Map<String,String> map = new HashMap<>();
        try{
            String phone = getTokenClaim(auth).getSubject();
            String shortTimeToken = getShortTimeToken(phone);
            String longTimeToken = getLongTimeToken(phone);
            map.put("short",shortTimeToken);
            map.put("long",longTimeToken);
        }catch (Exception e){
            System.out.println("长期token过期,请重新登录");
            map.put("202","请重新登录");
        }
        return map;
    }

    /*
     * 获取 Token 中注册信息
     */
    public Claims getTokenClaim (String token) {
        try {
            return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

}

刷新接口(示例):

    @ApiOperation(value = "admin",tags = "token刷新")
    @PostMapping("/refresh")
    public Map refresh(HttpServletRequest request){
        String authorization = request.getHeader("authorization-long");
        return jwtUtil.refresh(authorization);
    }

总结

提示:以上内容仅供参考:
如需demo案例请私信我。
小程序地址:https://github.com/CaseOfShe/school
演示地址:https://www.bilibili.com/video/BV1q3411g71P

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Token是一种用于身份验证的令牌,它在登录验证过程中起到了重要的作用。在登录时,服务器会对用户输入的账号密码进行验证,如果验证通过,服务器会创建一个token并将其发送给客户端。客户端会将token保存起来,并在下次登录时将token传递给服务器进行验证。如果token有效,用户就可以成功登录。\[1\] 基于Token的身份验证是一种无状态的验证方式,不需要在服务器端存储用户信息。这种方式解决了在服务端存储信息时可能出现的问题,同时也使得程序可以根据需要增减机器,而不用担心用户登录状态的问题。\[2\] Token也需要设定有效期,就像登录密码和安全证书一样。有效期的设定可以从安全性和吊销的角度考虑。定期更换Token可以增加系统的安全性,防止泄漏后被滥用。同时,设定有效期也可以解决吊销的问题,确保失效的Token不再被使用。关于有效期的具体长度,可以根据实际需求和安全策略来确定。\[3\] #### 引用[.reference_title] - *1* [token登录](https://blog.csdn.net/lovecoding1/article/details/124773169)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Token登录认证详解](https://blog.csdn.net/tc979907461/article/details/106288099)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值