最近在研究springboot-shiro基于JWT实现RBAC鉴权,那当然少不了JWT的颁发与校验,随之写了这个Demo,以供学习及未来记录之用
本文不会讲任何关于JWT
的知识点,因为相关内容的文章在互联网上很多
我在这里只放一个JWT的官网,大家有兴趣的可以看一下
接下来就是正文~
pom文件关键引入:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.6.0</version>
</dependency>
其他部分不放出,是一些基本引用,starter-web,lombok之类的
工具类JwtHelper
:
package xyz.xy718.util;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
/**
* JWT生成-校验工具
*<br>
* 今天熬夜了,难受
* @author Xy718
*/
@Component
public class JwtHelper {
//token 过期时间, 单位: 毫秒 7200000表示两小时
private static long TOKEN_EXPIRED_TIME;
@Value("${jwt.exp_time}")
public void setTOKEN_EXPIRED_TIME(Long tOKEN_EXPIRED_TIME) {
TOKEN_EXPIRED_TIME = tOKEN_EXPIRED_TIME;
}
private static String JWT_SECRET;
@Value("${jwt.secret}")
public void setJWT_SECRET(String jWT_SECRET) {
JWT_SECRET = jWT_SECRET;
}
/**
* 创建JWT
* @param username
* @return
*/
public static String createJWT(String username) {
//此处的map是带入到payload中的数据
Map<String, Object> map = new HashMap<>();
map.put("username", username);
//签名的加密算法
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
//当前时间
Date now = new Date(System.currentTimeMillis());
//签名
SecretKey secretKey = generalKey();
//下面就是在为payload添加各种标准声明和私有声明了
JwtBuilder builder = Jwts.builder()
.setClaims(map)//payload中的额外数据
.setId((int)(Math.random()*1000000)+"")//设置jti(JWT ID):是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为一次性token,从而回避重放攻击。
.setIssuedAt(now)//iat: jwt的签发时间
.signWith(signatureAlgorithm, secretKey);//设置签名使用的签名算法和签名使用的秘钥
//过期时间
long expMillis = now.getTime() + TOKEN_EXPIRED_TIME;
Date exp = new Date(expMillis);
//设置过期时间
builder.setExpiration(exp);
return builder.compact();
}
/**
* 验证JWT
* @param token
* @return
*/
public static Claims verifyJwt(String token) {
//签名秘钥,和生成的签名的秘钥一模一样
SecretKey key = generalKey();
Claims claims;
try {
claims = Jwts.parser()//得到DefaultJwtParser
.setSigningKey(key)//设置签名的秘钥
.parseClaimsJws(token).getBody();
} catch (Exception e) {
//校验失败
claims = null;
}
//抛出异常或null均为校验失败
return claims;
}
/**
* 由字符串生成加密key
* @return
*/
public static SecretKey generalKey() {
byte[] encodedKey=JWT_SECRET.getBytes();
SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
return key;
}
}
代码中都有注释,大家copy下来慢慢看即可~
application配置文件
上面工具类的代码看完的同学应该会注意到有两个变量是需要在配置文件中写入的
TOKEN_EXPIRED_TIME
和JWT_SECRET
这两个值分别代表了JWT的有效时间和签名加密秘钥
配置文件
:
jwt.secret=testkey
jwt.exp_time=7200000
使用(MainController)
package xyz.xy718.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import io.jsonwebtoken.Claims;
import xyz.xy718.model.JWTToken;
import xyz.xy718.util.JwtHelper;
import xyz.xy718.util.ResultBean;
@RestController
@RequestMapping("/jwt")
public class MainController {
@GetMapping("/create")
public ResultBean createJWT(
@RequestParam("username")String username
){
JWTToken retToken=new JWTToken();
retToken.setToken(JwtHelper.createJWT(username));
return ResultBean.success("登录成功",retToken);
}
@PostMapping("/verify")
public ResultBean verifyJWT(
@RequestBody JWTToken token
){
Claims claims=JwtHelper.verifyJwt(token.getToken());
if(claims==null){
return ResultBean.error("校验失败");
}
return ResultBean.success("校验成功",claims);
}
}
上面代码中的ResultBean
和JWTToken
相信有些同学一头雾水,不过不用担心,下文会放出本文得到github地址~
测试~
这里使用Postmen
模拟Restful访问
生成:
校验:
使用JWT官方检验工具也通过√
整个工具类的构建+测试就到这里结束啦~ 下面放出
github地址
有其他任何问题欢迎留言&联系我
冶心·练体·得技