1,什么是JJWT
JJWT是一个提供端到端的JWT创建和验证的Java库
token的创建
引入依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.6.0</version>
</dependency>
创建类CreateJwtTest,用于生成token` public class CreateJwtTest {
public static void main(String[] args) {
JwtBuilder builder= Jwts.builder().setId("888") .setSubject("小白")
.setIssuedAt(new Date())//设置签发时间
.signWith(SignatureAlgorithm.HS256,"xiaocai");//设置签名秘钥
System.out.println( builder.compact() );
// eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiLlsI_nmb0iLCJpYXQiOjE1MjM0MTM0NTh9.gq0JcOM_qCNqU_sd_IrRytaNenesPmqAIhQpYXHZk
}
}
// 再次运行,会发现每次运行的结果是不一样的,因为我们的载荷中包含了时间。
Token的解析
public class ParseJwtTest {
public static void main(String[] args) {
String
token="eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiLlsI_nmb0iLCJpYXQiO
jE1MjM0MTM0NTh9.gq0J‐cOM_qCNqU_s‐d_IrRytaNenesPmqAIhQpYXHZk";
Claims claims =
Jwts.parser().setSigningKey("xiaocai").parseClaimsJws(token).getBody();
System.out.println("id:"+claims.getId());
System.out.println("subject:"+claims.getSubject());
System.out.println("IssuedAt:"+claims.getIssuedAt());
}
}
token过期校验
public class CreateJwtTest2 {
public static void main(String[] args) {
//为了方便测试,我们将过期时间设置为1分钟
long now = System.currentTimeMillis();//当前时间
long exp = now + 1000*60;//过期时间为1分钟
JwtBuilder builder= Jwts.builder().setId("888")
.setSubject("小白")
.setIssuedAt(new Date())
.signWith(SignatureAlgorithm.HS256,"xiaocai")
.setExpiration(new Date(exp));//设置过期时间
System.out.println( builder.compact() );
}
}
public class ParseJwtTest {
public static void main(String[] args) {
String compactJws="eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiLlsI_nmb0iLCJpYXQiOjE1MjM0MTY1NjksImV4cCI6MTUyMzQxNjYyOX0.Tk91b6mvyjpKcldkic8DgXz0zsPFF
nRgTgkgcAsa9cc";
Claims claims = Jwts.parser()
.setSigningKey("xiaocai")
.parseClaimsJws(compactJws).getBody();
System.out.println("id:"+claims.getId());
System.out.println("subject:"+claims.getSubject());
SimpleDateFormat sdf=new SimpleDateFormat("yyyy‐MM‐dd hh:mm:ss");
System.out.println("签发时间:"+sdf.format(claims.getIssuedAt()));
System.out.println("过期时间:"+sdf.format(claims.getExpiration()));
System.out.println("当前时间:"+sdf.format(new Date()) );
}
}
自定义claims
public class CreateJwtTest3 {
public static void main(String[] args) {
//为了方便测试,我们将过期时间设置为1分钟
long now = System.currentTimeMillis();//当前时间
long exp = now + 1000*60;//过期时间为1分钟
JwtBuilder builder= Jwts.builder().setId("888")
.setSubject("小白")
.setIssuedAt(new Date()) .signWith(SignatureAlgorithm.HS256,"xiaocai") .setExpiration(new Date(exp)) .claim("roles","admin") .claim("logo","logo.png");
System.out.println( builder.compact() );
}
}
public class ParseJwtTest {
public static void main(String[] args) {
String
compactJws="eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiLlsI_nmb0iLCJp
YXQiOjE1MjM0MTczMjMsImV4cCI6MTUyMzQxNzM4Mywicm9sZXMiOiJhZG1pbiIsImxvZ28iO
iJsb2dvLnBuZyJ9.b11p4g4rE94rqFhcfzdJTPCORikqP_1zJ1MP8KihYTQ";
Claims claims =
Jwts.parser().setSigningKey("xiaocai").parseClaimsJws(compactJws).getBody();
System.out.println("id:"+claims.getId());
System.out.println("subject:"+claims.getSubject());
System.out.println("roles:"+claims.get("roles"));
System.out.println("logo:"+claims.get("logo"));
SimpleDateFormat sdf=new SimpleDateFormat("yyyy‐MM‐dd hh:mm:ss");
System.out.println("签发时间:"+sdf.format(claims.getIssuedAt()));
System.out.println("过期时 间:"+sdf.format(claims.getExpiration()));
System.out.println("当前时间:"+sdf.format(new Date()) );
}
}
JWT工具类
@Data
public class JwtUtil {
private String key; //密钥加盐
private long ttl; //过期时间
/**
* 生成JWT
*/
public String createJWT(String id, String subject, String role) {
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
JwtBuilder builder = Jwts.builder().setId(id)
.setSubject(subject)
.setIssuedAt(now)
.signWith(SignatureAlgorithm.HS256, key).claim("role", role);
if (ttl > 0) {
builder.setExpiration(new Date(nowMillis + ttl));
}
return builder.compact();
}
/**
* 解析JWT
*/
public Claims parseJWT(String jwtStr) {
return Jwts.parser()
.setSigningKey(key)
.parseClaimsJws(jwtStr)
.getBody();
}
}
添加配置
jwt:
config:
key: littledonkey
ttl: 3600000
签发token
//判断是否密码是否正确
Admin loginAdmin = adminService.login(admin);
if (loginAdmin == null) {
return new Result(false, StatusCode.LOGINERROR, "登陆失败");
}
//签发token
String token = jwtUtil.createJWT(admin.getId(), admin.getLoginname(), "admin");
HashMap<String, String> map = new HashMap<>();
map.put("token", token);
map.put("role", "admin");
return new Result(true, StatusCode.OK, "登陆成功", map);
添加拦截器
@Component
public class TokenInterceptor implements HandlerInterceptor {
@Autowired
private JwtUtil jwtUtil;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取请求头(如果有此请求头,表示token已经签发)
String header = request.getHeader("tokenHeader");
if (header != null || !"".equals(header)) {
//解析请求头(防止伪造token,token内容以"token "作为开头)
if (header.startsWith("token ")) {
try {
Claims claims = jwtUtil.parseJWT(header.substring(6));
String role = (String) claims.get("role");
//为具有相关权限的用户添加权限到request域中
if ("admin".equals(role)) {
//拿到"admin_token"头信息,表示当前角色是admin
request.setAttribute("admin_token", header.substring(6));
}
if ("user".equals(role)) {
//拿到"user_token"头信息,表示当前角色是user
request.setAttribute("user_token", header.substring(6));
}
} catch (Exception e) {
throw new RuntimeException("令牌不正确");
}
}
}
//所有请求都通过,具体权限在service层判断
return true;
}
}
注册拦截器
@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport {
@Autowired
private TokenInterceptor tokenInterceptor;
@Override
protected void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(tokenInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/login/**");
}
}
service层验证
public void deleteById(String id) {
String admin_token = (String) request.getAttribute("admin_token");
if(admin_token == null || "".equals(admin_token)){
throw new RuntimeException("权限不足");
}
adminDao.deleteById(id);
}