SSM下的JWT配置
1.简介
随着互联网的不断发展,技术的迭代也非常之快。我们的用户认证也从刚开始的用户名密码转变到基于cookie的session认证,然而到了今天,这种认证已经不能满足与我们的业务需求了(分布式,微服务)。我们采用了另外一种认证方式:基于token的认证。
一、与cookie相比较的优势:
1、支持跨域访问,将token置于请求头中,而cookie是不支持跨域访问的;
2、无状态化,服务端无需存储token,只需要验证token信息是否正确即可,而session需要在服务端存储,一般是通过cookie中的sessionID在服务端查找对应的session;
3、无需绑定到一个特殊的身份验证方案(传统的用户名密码登陆),只需要生成的token是符合我们预期设定的即可;
4、更适用于移动端(Android,iOS,小程序等等),像这种原生平台不支持cookie,比如说微信小程序,每一次请求都是一次会话,当然我们可以每次去手动为他添加cookie,详情请查看博主另一篇博客;
5、避免CSRF跨站伪造攻击,还是因为不依赖cookie;
6、非常适用于RESTful API,这样可以轻易与各种后端(java,.net,python…)相结合,去耦合
JWT:JSON Web Token,其实token就是一段字符串,由三部分组成:Header,Payload,Signature。
- 在微信小程序中,我们可以通过自己定义的Token,来更便捷地定义登录的信息获取
- 还可以在Shiro中通过自己定义的Token来决定是否允许登录
- 等等…
2.开始
首先导入对应的maven依赖:
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.1</version>
</dependency>
写工具类TokenUtil.java
package com.BookKeeping.util;
import com.BookKeeping.entity.Token;
import com.BookKeeping.entity.User;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class TokenUtil {
//过期时间设置(30分钟)
private static final long EXPIRE_TIME = 30*60*1000;
//私钥设置(随便乱写的)
private static final String TOKEN_SECRET = "5xcJVrXNyQDIxK1l2RS9nw";
public String getToken(Token token){
//过期时间和加密算法设置
Date date=new Date(System.currentTimeMillis()+EXPIRE_TIME);
Algorithm algorithm =Algorithm.HMAC256(TOKEN_SECRET);
//头部信息
Map<String,Object> header=new HashMap<>(2);
header.put("typ","JWT");
header.put("alg","HS256");
return JWT.create()
.withHeader(header)
.withClaim("openId",token.getOpenId())
.withClaim("role",token.getRole())
.withClaim("lastLogin",token.getLastLogin())
.withExpiresAt(date)
.sign(algorithm);
}
public Token getTokenData(String token){
DecodedJWT jwt = JWT.decode(token);
Token tk = new Token();
tk.setOpenId(jwt.getClaim("openId").asString());
tk.setRole(jwt.getClaim("role").asString());
tk.setLastLogin(jwt.getClaim("lastLogin").asDate());
return tk;
}
public String creatToken(String openid,String role){
//这里是传入的是token对象,决定token的内容
Token tk=new Token();
//获取时间用
Date date=new Date();
tk.setOpenId(openid);
tk.setRole(role);
tk.setLastLogin(date);
//交给上面的实现类得到token
return getToken(tk);
}
public String getTokenDataOpenId(String token){
return JWT.decode(token).getClaim("openId").asString();
}
}
token实体类,可以根据需求变更,右键生成get,set,tostring,
package com.BookKeeping.entity;
import java.util.Date;
public class Token {
private Integer id;
private String openId;
private String role;
private Date lastLogin;
}
此时调用creatToken即可获得对应数据得到的token
在测试类中编写如下内容测试:
@Test
//Token加解密测试
public void TokenTest(){
TokenUtil tku=new TokenUtil();
Token tk=new Token();
String result=tku.creatToken("asdfghjkl","admin");
System.out.println(result);
tk=tku.getTokenData(result);
System.out.println(tk.toString());
}
结果:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsYXN0TG9naW4iOjE1ODA0NDM0NTYsInJvbGUiOiJhZG1pbiIsIm9wZW5JZCI6ImFzZGZnaGprbCIsImV4cCI6MTU4MDQ0NTI1Nn0.a3DRBuM2g_BODTf142RO6JWAMPVE3voJZvuWSioX_Yo
Token{id=null, openId='asdfghjkl', role='admin', lastLogin=Fri Jan 31 12:04:16 GMT+08:00 2020}