Java 的 JJWT 实现 JWT
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,但未进行页面渲染)、返回处理(已经渲染了页面):
- 在preHandle中,可以进行编码、安全控制等处理
- 在postHandle中,有机会修改ModelAndView
- 在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);
}
Java 的 JJWT 实现 JWT的更多相关文章
- Spring Security + JJWT 实现 JWT 认证和授权
关于 JJWT 的使用,可以参考之前的文章:JJWT 使用示例 一.鉴权过滤器 @Component public class JwtAuthenticationTokenFilter extends ...
- SpringBoot系列之前后端接口安全技术JWT
@ 目录 1. 什么是JWT? 2. JWT令牌结构怎么样? 2.1 标头(Header) 2.2 有效载荷(Playload) 2.3 签名(Signature) 3. JWT原理简单介绍 4. J ...
- Java JWT: JSON Web Token
Java JWT: JSON Web Token for Java and Android JJWT aims to be the easiest to use and understand libr ...
- 各类JWT库(java)的使用与评价
[搬运工] 出处:http://andaily.com/blog/?p=956 在 https://jwt.io/ 网站中收录有各类语言的JWT库实现(有关JWT详细介绍请访问 https://jwt ...
- 手写jwt验证,实现java和node无缝切换
前言 前端时间和我朋友写了一个简易用户管理后台,功能其实很简单,涉及到的技术栈有:vue+elementUI,java+spring MVC以及node+egg,数据库用的mysql,简单方便. 一开 ...
- 通过webgoat-xxe、jwt学习Java代码审计
WebGoat-JWT JWT Tokens 01 概念 本课程将介绍如何使用JSON Web Token(JWT)进行身份验证,以及在使用JWT时需要注意的常见陷阱. 目标 教授如何安全地实现令牌的 ...
- spring cloud实战与思考(五) JWT之携带敏感信息
需求: 需要将一些敏感信息保存在JWT中,以便提高业务处理效率. 众所周知JWT协议RFC7519使用Base64Url对Header和Payload的Json字符串进行编解码.A JWT is re ...
- 基于jwt和角色的访问控制解决方案
0,主要解决两个问题:1身份验证(防止httpclient拼接请求),2权限控制 1,身份验证使用jwt,在java就是jjwt jwt可以比较好的整合restful,对无状态客户端比较友好,(用se ...
- JWT+Interceptor实现无状态登录和鉴权
无状态登录原理 先提一下啥是有状态登录 单台tomcat的情况下:编码的流程如下 前端提交表单里用户的输入的账号密码 后台接受,查数据库, 在数据库中找到用户的信息后,把用户的信息存放到session ...
随机推荐
- LeetCode 176. Second Highest Salary (第二高的薪水)
题目标签: 题目给了我们一个工资表,让我们返回第二高的工资. 利用Max,把第一高的工资找到,然后利用 NOT IN,去找到第二高的工资. Java Solution: Runtime: 153ms ...
- POJ 3761 Bubble Sort
题目链接:https://vjudge.net/problem/POJ-3761 转自:https://blog.csdn.net/cscj2010/article/details/7820906 题 ...
- nutch2.2.1+mysql抓取数据
基本环境:linux centos6.5 nutch2.2.1 源码包, mysql 5.5 ,elasticsearch1.1.1, jdk1.7 1.下载地址http://mirror.bjtu. ...
- 全球CMOS图像传感器厂商
近期,台湾地区的Yuanta Research发布报告,介绍了其对CMOS图像传感器(CIS)市场的看法,以及到2022年的前景预期. 从该研究报告可以看出,2018年全球CMOS图像传感器的市场规模 ...
- vue中解决拖动和点击事件的冲突
BUG说明: 鼠标上下方向拖拽,如果松开时鼠标位于悬浮按钮上会默认执行click事件,经验证,click事件与mouse事件的执行顺序为onmousedown =>onmouseup => ...
- JS函数 函数调用 函数定义好后,是不能自动执行的,需要调用它,直接在需要的位置写函数名。
函数调用 函数定义好后,是不能自动执行的,需要调用它,直接在需要的位置写函数名. 第一种情况:在<script>标签内调用. <script type="text/java ...
- PHP算法之两数相加
给出两个 非空 的链表用来表示两个非负的整数.其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字. 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和 ...
- linux上给其他在线用户发送信息(wall, write, talk, mesg)
linux上给其他在线用户发送信息(wall, write, talk, mesg) 2018-01-05 lonskyMR 转自 恶之一眉 修改 微信分享: 设置登录提示 /et ...
- [JZOJ3402] 【GDOI2014模拟】Pty的字符串
题目 给你一棵每条边从父亲指向儿子的树,每条边上面有一个字母. 从树上的任意一点出发,走出的路径就是对应一个子串. (这不是\(Trie\),因为每个父亲可能会连出字母相同的边) 再给你一个字符串\( ...
- springboot2.x jpa接入多数据源
环境:springboot 2.1.4 数据源引入方式 数据源一 @Configuration @EnableTransactionManagement @EnableJpaRepositories( ...