Spring JWT 生成 Token

Spring Jwt 生成 Token

由来

当前后端结合的时候可以根据请求返回数据,在服务端储存 cookie,session 等,但当前后端分离后,不光后端无法渲染前端,还会收到许多前端传来的请求,这时就需要 token 来验证用户信息。

Token

Token 是在服务端产生的。如果前端使用用户名/密码向服务端请求认证,服务端认证成功,那么在服务端会返回 Token 给前端。前端可以在每次请求的时候带上 Token 证明自己的合法地位。如果这个 Token 在服务端持久化(比如存入数据库),那它就是一个永久的身份令牌。
为防止密码等信息的泄露,常常是前端只传递 Token 除登陆等少量操作不会传递有关用户信息的内容,而 Token 也可以时常更新,以保证安全性。

JWT

在 java 中 JWT 便是生成 Token 的非常方便的工具。
可以用来验证用户身份以及对路由,服务和资源的访问权限进行验证。

结构

JWT是由三段信息构成的,例如:
eyJhbGciOiJIUzI1NiJ9.
eyJqdGkiOiJjOTRmMTYyNy00MzMxLTQzZmMtYWY4My1iNmM5ZTA1M2UzNTIiLCJpYXQiOjE1NjcwODQ1MzUsInN1YiI6InN5c3RlbSIsImlzcyI6Im5weSIsInVzZXJJZCI6MTM4OSwidXNlcm5hbWUiOiIxMSIsImV4cCI6MTU2NzE5MjUzNX0.
hUssKQEWZwg59tCls7FseXtvkde6XQ44FVSM1R437Rw

Header

JWT的头部承载两部分信息:token类型和采用的加密算法。
{
“alg”: “HS256”,
“typ”: “JWT”
}
声明加密的算法:有许多种,选择自己想要的就好,一般编程软件会有提示

Payload

载荷就是存放有效信息的地方。
有效信息包含三个部分

  1. 标准中注册的声明
  2. 公共的声明
  3. 私有的声明

标准中注册的声明 (建议但不强制使用) :
iss: JWT 签发者
sub: 面向的用户(JWT 所面向的用户)
aud: 接收 JWT 的一方
exp: 过期时间戳(jwt的过期时间,这个过期时间必须要大于签发时间)
nbf: 定义在什么时间之前,该 JWT 都是不可用的.
iat: jwt的签发时间
jti: jwt的唯一身份标识,主要用来作为一次性 Token,从而回避重放攻击。

secret

这个部分需要 base64 加密后的 header 和 base64 加密后的 payload 使用。连接组成的字符串,然后通过 header 中声明的加密方式进行加盐值 secret 组合加密,然后就构成了 JWT 的第三部分。
密钥secret是保存在服务端的,服务端会根据这个密钥进行生成token和进行验证,所以需要保护好。

依赖注入

如今常见的依赖有两种(本文以第二种为例):

<dependency>
      <groupId>com.auth0</groupId>
      <artifactId>java-jwt</artifactId>
      <version>3.4.0</version>
</dependency>
<dependency>
      <groupId>io.jsonwebtoken</groupId>
      <artifactId>jjwt</artifactId>
      <version>0.9.0</version>
</dependency>

代码实现

User类自己实现就好,简单的面向对象。

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

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

public class JwtUtil {

    /**
     * 获取token
     * @param encryKey
     * @param minutes
     * @return
     */
    public static String getToken(User user, String encryKey, long minutes){
        long currentTime = System.currentTimeMillis();
        //也可以直接传入 Map<String, Object> 做简单的修改即可
        Map<String, Object> map = new HashMap<>();
        map.put("userId", user.getId());
        return Jwts.builder()
                .setId(UUID.randomUUID().toString()) //当前用户
                .setIssuedAt(new Date()) //签发日期
                .setSubject("system") //说明
                .setIssuer("npy") //签发者信息
                .signWith(SignatureAlgorithm.HS256, encryKey) //加密方式
                .addClaims(map)
                .setExpiration(new Date(currentTime + minutes * 1000 * 60)) //过期时间
                .compact();
    }

    /**
     * 验证是否到时间
     * @param token
     * @param encryKey
     * @return
     */
    public static boolean isExpiration(String token, String encryKey){
        try {
            long currentTime = System.currentTimeMillis();
            if (Jwts.parser().setSigningKey(encryKey).parseClaimsJws(token).getBody().getExpiration().after(new Date(currentTime))){
                return true;
            }else {
                return false;
            }
        }catch (Exception e){
            return false;
        }
    }

    /**
     * 获取claims
     * @param token
     * @param encryKey
     * @return
     */
    public static Claims getClamis(String token, String encryKey){
        try {
            Claims claims = Jwts.parser().setSigningKey(encryKey).parseClaimsJws(token).getBody();
            return claims;
        }catch (Exception e){
            return null;
        }
    }

//    public static void main(String[] args) {
//        String token =
//"eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJjOTRmMTYyNy00MzMxLTQzZmMtYWY4My1iNmM5ZTA1M2UzNTIiLCJpYXQiOjE1NjcwODQ1MzUsInN1YiI6InN5c3RlbSIsImlzcyI6Im5weSIsInVzZXJJZCI6MTM4OSwidXNlcm5hbWUiOiIxMSIsImV4cCI6MTU2NzE5MjUzNX0.hUssKQEWZwg59tCls7FseXtvkde6XQ44FVSM1R437Rw";
//        System.out.println(JwtUtil.getClamis(token, "salt").get("userId"));
//        System.out.println(JwtUtil.getClamis(token, "salt").get("username"));
//    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值