JWT实现token

JWT是什么?

        JWT的本质就是一个字符串,它是将用户信息保存到一个Json字符串中,然后进行编码后得到一个JWT token,并且这个JWT token带有签名信息,接收后可以校验是否被篡改,所以可以用于在各方之间安全地将信息作为Json对象传输。

JWT的认证流程如下:

1、首先,前端通过Web表单将自己的用户名和密码发送到后端的接口,这个过程一般是一个POST请求。建议的方式是通过SSL加密的传输(HTTPS),从而避免敏感信息被嗅探

2、后端核对用户名和密码成功后,将包含用户信息的数据作为JWT的Payload,将其与JWT Header分别进行Base64编码拼接后签名,形成一个JWT Token,形成的JWT Token就是一个如同lll.zzz.xxx的字符串 3、后端将JWT Token字符串作为登录成功的结果返回给前端。前端可以将返回的结果保存在浏览器中,退出登录时删除保存的JWT Token即可

4、前端在每次请求时将JWT Token放入HTTP请求头中的Authorization属性中(解决XSS和XSRF问题)

5、后端检查前端传过来的JWT Token,验证其有效性,比如检查签名是否正确、是否过期、token的接收方是否是自己等等

6、验证通过后,后端解析出JWT Token中包含的用户信息,进行其他逻辑操作(一般是根据用户信息得到权限等),返回结果

JWT:JSON Web Token,token就是一段字符串,由三部分组成:Header,Payload,Signature

Header

JWT头部分是一个描述JWT元数据的JSON对象,通常如下所示。

{
"alg": "HS256",
"typ": "JWT"
}

        在上面的代码中,alg属性表示签名使用的算法,默认为HMAC SHA256(写为HS256);typ属性表示令牌的类型,JWT令牌统一写为JWT。最后,使用Base64 URL算法将上述JSON对象转换为字符串保存。

Payload        

        有效载荷部分,是JWT的主体内容部分,也是一个JSON对象,包含需要传递的数据。 JWT指定七个默认字段供选择。

iss:发行人
exp:到期时间
sub:主题
aud:用户
nbf:在此之前不可用
iat:发布时间
jti:JWT ID用于标识该JWT

除以上默认字段外,我们还可以自定义私有字段,如下例:

{
"userId": "1",
"userAccount": "wupengyu",
}

Signature

一段签名数据

类似于:

SING="ahfuau&@$&@$@%";

JWT使用步骤

1、导入maven依赖

这里使用的时auth0中的jwt,hutool中也有jwt,此处不再过多研究

<!--   JWT     -->
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.4.0</version>
</dependency>

2、编写JWTUtils工具包

此处可以作为通用JWT工具类

public class JWTUtils {
    private static final String SING = "!Q@W3e4r%T^Y";
    /**
     *  生成token  header.payload.sing
     * */
    public static String getToken(Map<String,String> map){
        //获取当前时间
        Calendar instance = Calendar.getInstance();
        //Calendar中add,对天数进行操作,设置当前时间后七天
        instance.add(Calendar.DATE,7);
        //创建JWT builder
        JWTCreator.Builder builder = JWT.create();
        //设置payload
        map.forEach((k,v)->{
                builder.withClaim(k,v);
        });
        String token = builder
                .withExpiresAt(instance.getTime())//指定令牌过期时间
                .sign(Algorithm.HMAC256(SING));
        System.out.println(token);
        return token;
    }
​
    /**
     *  验证token 合法性
     * */
    public static void verify(String token){
        //验签算法,要与签名算法相同
         JWT.require(Algorithm.HMAC256(SING)).build().verify(token);
    }
​
    /**
     *  获取token信息
     * */
    public static DecodedJWT getTokenInfo(String token){
        DecodedJWT decodedJWT = JWT.require(Algorithm.HMAC256(SING)).build().verify(token);
        //从DecodedJWT中拿token的信息
        return decodedJWT;
    }
}

3、编写token的拦截器

        如果在每个接口处都对token进行校验,会造成代码冗余,所以我们写一个拦截器或者AOP,如果是分布式系统,那就将此操作写进网关。

public class JWTInterceptor implements HandlerInterceptor {
​
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        Map<String,Object> map = new HashMap<>();
        //获取请求头中的令牌
        String token = request.getHeader("token");
        try{
            JWTUtils.verify(token);//验证令牌
            return true;//请求放行
        }catch (SignatureVerificationException e){
            e.printStackTrace();
            map.put("msg","无效签名");
        }catch (TokenExpiredException e){
            e.printStackTrace();
            map.put("msg","token过期");
        }catch (AlgorithmMismatchException e){
            e.printStackTrace();
            map.put("msg","token算法不一致");
        }catch (Exception e){
            e.printStackTrace();
            map.put("msg","token无效");
        }
        map.put("state",false);
        //将map转化为json
        Gson gson = new Gson();
        String json = gson.toJson(map);
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().print(json);
        return false;
    }
}

4、配置token拦截器

        自主选择不需要拦截的路径进行配置即可

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
​
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new JWTInterceptor())
                .addPathPatterns("/user/**")
                .excludePathPatterns("/user/login")
                .excludePathPatterns("/user/login/byPhone")
                .excludePathPatterns("/user/sendMsg");
​
    }
}

5、之后,在登录接口中,用户登陆成功后,生成一个token,并作为响应值返回给前端,前端将其设置到请求头中。如需使用token中的用户信息,调用token的解析方法就可以。

扩展:如果想注销时删除token,除了在前端删除请求头外,还应设置黑名单,可以使用redis设置黑名单,防止恶意使用还未过期的token进行数据访问。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
JWT实现token销毁的方式有几种方法。一种常见的方法是将token存储在服务器端的黑名单中。当用户注销或需要销毁token时,将该token添加到黑名单中。在每次请求时,服务器会检查token是否在黑名单中,如果是,则拒绝该请求。这种方法需要服务器维护一个黑名单列表,并增加一些额外的逻辑来检查token的有效性。\[2\] 另一种方法是使用token的过期时间来实现销毁。在生成token时,可以设置一个过期时间,一旦token过期,它将自动失效。这样,即使token被保留在客户端,一旦过期,它也无法再被使用。这种方法不需要服务器维护黑名单列表,但需要在生成token设置合适的过期时间。\[3\] 需要注意的是,JWT本身是无状态的,它不提供直接的注销功能。因此,实现token销毁需要额外的逻辑和控制。具体的实现方式可以根据具体的需求和系统架构来选择。 #### 引用[.reference_title] - *1* [SpringBoot集成JWT实现token验证,token注销](https://blog.csdn.net/yangyangye/article/details/117445245)[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^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [如何使用jwt 完成注销(退出登录)功能](https://blog.csdn.net/weixin_39813433/article/details/122287823)[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^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值