JJWT是一个提供端到端的JWT创建和验证的Java库

依赖

        <dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>RELEASE</version>
</dependency>

token的创建

setIssuedAt用于设置签发时间
signWith用于设置签名秘钥 JwtBuilder builder = Jwts.builder().setId("111")
.setSubject("小明")
.setIssuedAt(newDate())
.signWith(SignatureAlgorithm.HS256, "ld"); String token = builder.compact();

token的解析

        String token = "~~~";
Claims claims = Jwts.parser().setSigningKey("ld").parseClaimsJws(token).getBody();
System.out.println("id:" + claims.getId());
System.out.println("subject:" + claims.getSubject());
System.out.println("IssuedAt:" + claims.getIssuedAt());

token过期校验

        long now = System.currentTimeMillis();  //当前时间
long exp = now + 1000 * 60; //过期时间为1分钟
JwtBuilder builder = Jwts.builder().setId("111")
.setSubject("小明")
.setIssuedAt(new Date())
.signWith(SignatureAlgorithm.HS256, "ld")
.setExpiration(new Date(exp)); 当未过期时可以正常读取
当过期时会引发 io.jsonwebtoken.ExpiredJwtException 异常

自定义claims

        long now = System.currentTimeMillis();  //当前时间
long exp = now + 1000 * 60; //过期时间为1分钟
JwtBuilder builder = Jwts.builder().setId("111")
.setSubject("小明")
.setIssuedAt(new Date())
.signWith(SignatureAlgorithm.HS256, "ld")
.setExpiration(new Date(exp))
.claim("role", "admin"); 获取:
claims.get("role")

示例

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);

使用拦截器方式实现token鉴权

org.springframework.web.servlet.handler.HandlerInterceptorAdapter这个适配器,

继承此类,可以非常方便的实现自己的拦截器。

三个方法分别实现预处理、后处理(调用了Service并返回ModelAndView,但未进行页面渲染)、返回处理(已经渲染了页面):

  1. 在preHandle中,可以进行编码、安全控制等处理
  2. 在postHandle中,有机会修改ModelAndView
  3. 在afterCompletion中,可以根据ex是否为null判断是否发生了异常,进行日志记录
添加拦截器

@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);
}

最新文章

  1. Ruby Gem命令详解
  2. 【转】c#获取网页地址参数
  3. [MISSAJJ原创] UITableViewCell移动及翻转出现的3D动画效果[58同城cell移动效果]
  4. C++迟后联编和虚函数表
  5. Java中的构造代码块
  6. 奇葩啊,HOLOLENS里模拟器截不了图,后台DEVIE PORTAL可以截
  7. [Elixir007] on_definition规范函数定义时的各种潜规则
  8. Practical Machine Learning For The Uninitiated
  9. each的详解
  10. jsp 是什么 ,jsp 隐式对象
  11. Android中定时器的3种实现方法
  12. springmvc(五)----异常处理
  13. .Net之美读书系列(二):委托进阶
  14. Git存储用户名和密码(明文需谨慎)
  15. Selenium2+python自动化28-table定位
  16. SVN上传项目步骤
  17. protobuf、LRU、sigleflight
  18. pytest使用简介
  19. js截取url参数
  20. hbase--知识点总结2

热门文章

  1. Vue.js框架的基础指令
  2. 顺时针打印矩阵元素(python实现)
  3. xml初步,DTD和Schema约束
  4. mysql8以上版本时区问题:The server time zone value乱码XXXX
  5. unittest(2)
  6. 三层(3-tier architecture)基础
  7. Linux queue.h之TAILQ队列分析
  8. Java获取文件Content-Type(Mime-Type)
  9. Codeforces 553E Kyoya and Train
  10. [JZOJ4665] 【GDOI2017模拟7.21】数列