jwt快速入门

1.介绍

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

实现是 一个 加密的字符串 ,这个字符串存储了用户的身份凭证 等信息

JWT一般不要携带太大的数据,不然每次请求都要处理太费时,所以一般是用JWT做认证,然后去redis里面取相应的角色权限信息。

2.快速开始

2.1添加依赖

 <!-- JWT -->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.7.0</version>
        </dependency>

2.2创建工具类

package com.zhp.sbdemo1.utils;
​
import com.zhp.sbdemo1.common.CheckResult;
import com.zhp.sbdemo1.common.SystemConstant;
import io.jsonwebtoken.*;
import org.bouncycastle.util.encoders.Base64;
​
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;
​
/**
 * 前端发送认证请求   比如用户名密码   认证通过后  后台生成一个 token
 * 发送给前端  前端存储到 localstorage    以后每次请求 都带这个token  发送到后台 去验证
 *
 *
 *
 * @date 2021/5/9 20:44
 */
public class JwtUtils {
​
    /**
     * 签发JWT
     * @param id
     * @param subject 可以是JSON数据 尽可能少
     * @param ttlMillis
     * @return
     */
    public static String createJWT(String id, String subject, long ttlMillis) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        SecretKey secretKey = generalKey();
        JwtBuilder builder = Jwts.builder()
                .setId(id)
                .setSubject(subject)   // 主体  一般是用户名
                .setIssuer("axbhealj")     // 签发者
                .setIssuedAt(now)      // 签发时间
                .signWith(signatureAlgorithm, secretKey); // 签名算法以及密匙
        if (ttlMillis >= 0) {
            long expMillis = nowMillis + ttlMillis;  // 当前时间  + 有效时间
            Date expDate = new Date(expMillis);   // 过期时间
            builder.setExpiration(expDate); // 设置过期时间
        }
        return builder.compact();
    }
​
    /**
     * 验证JWT
     * @param jwtStr
     * @return
     */
    public static CheckResult validateJWT(String jwtStr) {
        CheckResult checkResult = new CheckResult();
        Claims claims = null;
        try {
            claims = parseJWT(jwtStr);
            checkResult.setSuccess(true);
            checkResult.setClaims(claims);
        } catch (ExpiredJwtException e) {
            checkResult.setErrCode(SystemConstant.JWT_ERRCODE_EXPIRE);
            checkResult.setSuccess(false);
        } catch (SignatureException e) {
            checkResult.setErrCode(SystemConstant.JWT_ERRCODE_FAIL);
            checkResult.setSuccess(false);
        } catch (Exception e) {
            checkResult.setErrCode(SystemConstant.JWT_ERRCODE_FAIL);
            checkResult.setSuccess(false);
        }
        return checkResult;
    }
​
    /**
     * 生成加密Key
     * @return
     */
    public static SecretKey generalKey() {
        byte[] encodedKey = Base64.decode(SystemConstant.JWT_SECERT);
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }
​
​
    /**
     * 解析JWT字符串
     * @param jwt
     * @return
     * @throws Exception
     */
    public static Claims parseJWT(String jwt) throws Exception {
        SecretKey secretKey = generalKey();
        return Jwts.parser()
                .setSigningKey(secretKey)
                .parseClaimsJws(jwt)
                .getBody();
    }
​
    public static void main(String[] args) throws InterruptedException {
         // 后端生成token
        String sc=createJWT("1","jack",SystemConstant.JWT_TTL);
        System.out.println(sc);
​
        // 后端验证token
        CheckResult checkResult = validateJWT(sc);
        System.out.println(checkResult.isSuccess());
        System.out.println(checkResult.getErrCode());
        Claims claims=checkResult.getClaims();
        System.out.println(claims);
        System.out.println(claims.getId());
        System.out.println(claims.getSubject());
​
        // 刷新token 重新生成token
        Claims claims2=validateJWT(sc).getClaims();
        String sc2=createJWT(claims2.getId(),claims2.getSubject(),SystemConstant.JWT_TTL);
        System.out.println(sc2);
    }
​
}

配套 常量类 和 结果类

package com.zhp.sbdemo1.common;
​
/**
 * @date 2023/5/24
 * @desc
 */
public class SystemConstant {
    /**
     * token
     */
    public static final int JWT_ERRCODE_NULL = 4000;            //Token不存在
    public static final int JWT_ERRCODE_EXPIRE = 4001;          //Token过期
    public static final int JWT_ERRCODE_FAIL = 4002;            //验证不通过
​
    /**
     * JWT
     */
    public static final String JWT_SECERT = "8677df7fc3a34e26a61c034d5ec8245d";         //密匙
    public static final long JWT_TTL = 30 * 60 * 1000;                                  //token有效时间
}
​
package com.zhp.sbdemo1.common;
​
import io.jsonwebtoken.Claims;
​
/**
 * @date 2023/5/24
 * @desc
 */
public class CheckResult {
​
    private int errCode;
​
    private boolean success;
​
    private Claims claims;
​
    public int getErrCode() {
        return errCode;
    }
​
    public void setErrCode(int errCode) {
        this.errCode = errCode;
    }
​
    public boolean isSuccess() {
        return success;
    }
​
    public void setSuccess(boolean success) {
        this.success = success;
    }
​
    public Claims getClaims() {
        return claims;
    }
​
    public void setClaims(Claims claims) {
        this.claims = claims;
    }
}

3.认证成功 发送token

 @PostMapping("/login")
    public JsonResult login(@RequestBody User user){
        User currentUser = userService.login(user);
        if(currentUser==null){
            //认证失败
            return JsonResult.ok(currentUser);
        }else {
            //认证成功  向前端 发送token
            String token =   JwtUtils.createJWT(String.valueOf(currentUser.getUserId()),currentUser.getRealname(), SystemConstant.JWT_TTL);
            return JsonResult.ok(token);
        }
    }

4.前端接受token 并存起来 以后每次请求在请求头上携带token

   //整合  jwt  返回的是  token     后面的请求  就需要携带token
               var token  = resp.data.data;
                //把响应结果的token 存到 localStorage
               window.localStorage.setItem("token",token);

后续请求携带token

 let token = window.localStorage.getItem("token");
        
        this.axios.defaults.headers.common["token"] = token;  // 请求头上带token

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在创建项目时,可以使用Maven将com.auth0的java-jwt依赖项添加到pom.xml中。 关于为什么要使用两个JWT token的问题,原因是这两个token有不同的职责。access token用于业务系统交互,是最核心的数据,而refresh token则用于向认证中心获取新的access token和refresh token。当用户超过30分钟后,access token已经失效,此时将access token发送给认证中心是无法解析的。但refresh token由于生存时间更长且与access token的主体内容一致,因此发送给认证中心后可以被正确解析,并生成新的access token和refresh token。这样就能实现token的替换和更新。 在JWT中,还有一些标准的声明,包括注册的声明和私有的声明。注册的声明是一些标准中推荐使用的声明,包括iss(jwt签发者)、sub(jwt所面向的用户)、aud(接收jwt的一方)、exp(jwt的过期时间)、nbf(定义在什么时间之前该jwt是不可用的)、iat(jwt的签发时间)和jti(jwt的唯一身份标识,用于防止重放攻击)。 所以,jwt token依赖包括com.auth0的java-jwt和相关的标准声明。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [DecodeIdToken:通过JWT解码ID TOKEN](https://download.csdn.net/download/weixin_42138788/15396844)[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^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [JWT快速入门及所需依赖](https://blog.csdn.net/huangziweilii/article/details/128334713)[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^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值