pom.xml


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

JwtUtil.java


package com.app.core.util; import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.crypto.MacProvider;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime; import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.util.Date;
import java.util.UUID; /**
* JWT校验工具类
* <ol>
* <li>iss: jwt签发者</li>
* <li>sub: jwt所面向的用户</li>
* <li>aud: 接收jwt的一方</li>
* <li>exp: jwt的过期时间,这个过期时间必须要大于签发时间</li>
* <li>nbf: 定义在什么时间之前,该jwt都是不可用的</li>
* <li>iat: jwt的签发时间</li>
* <li>jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击</li>
* </ol>
*/
@Log4j2
public class JwtUtil {
/**
* JWT 加解密类型
*/
private static final SignatureAlgorithm JWT_ALG = SignatureAlgorithm.HS256;
/**
* JWT 生成密钥使用的密码
*/
private static final String JWT_RULE = "wjtree.xin"; /**
* JWT 添加至HTTP HEAD中的前缀
*/
private static final String JWT_SEPARATOR = "Bearer "; /**
* 使用JWT默认方式,生成加解密密钥
*
* @param alg 加解密类型
* @return
*/
public static SecretKey generateKey(SignatureAlgorithm alg) {
return MacProvider.generateKey(alg);
} /**
* 使用指定密钥生成规则,生成JWT加解密密钥
*
* @param alg 加解密类型
* @param rule 密钥生成规则
* @return
*/
public static SecretKey generateKey(SignatureAlgorithm alg, String rule) {
// 将密钥生成键转换为字节数组
byte[] bytes = Base64.decodeBase64(rule);
// 根据指定的加密方式,生成密钥
return new SecretKeySpec(bytes, alg.getJcaName());
} /**
* 构建JWT
*
* @param alg jwt 加密算法
* @param key jwt 加密密钥
* @param sub jwt 面向的用户
* @param aud jwt 接收方
* @param jti jwt 唯一身份标识
* @param iss jwt 签发者
* @param nbf jwt 生效日期时间
* @param duration jwt 有效时间,单位:秒
* @return JWT字符串
*/
public static String buildJWT(SignatureAlgorithm alg, Key key, String sub, String aud, String jti, String iss, Date nbf, Integer duration) {
// jwt的签发时间
DateTime iat = DateTime.now();
// jwt的过期时间,这个过期时间必须要大于签发时间
DateTime exp = null;
if (duration != null)
exp = (nbf == null ? iat.plusSeconds(duration) : new DateTime(nbf).plusSeconds(duration)); // 获取JWT字符串
String compact = Jwts.builder()
.signWith(alg, key)
.setSubject(sub)
.setAudience(aud)
.setId(jti)
.setIssuer(iss)
.setNotBefore(nbf)
.setIssuedAt(iat.toDate())
.setExpiration(exp != null ? exp.toDate() : null)
.compact(); // 在JWT字符串前添加"Bearer "字符串,用于加入"Authorization"请求头
return JWT_SEPARATOR + compact;
} /**
* 构建JWT
*
* @param sub jwt 面向的用户
* @param aud jwt 接收方
* @param jti jwt 唯一身份标识
* @param iss jwt 签发者
* @param nbf jwt 生效日期时间
* @param duration jwt 有效时间,单位:秒
* @return JWT字符串
*/
public static String buildJWT(String sub, String aud, String jti, String iss, Date nbf, Integer duration) {
return buildJWT(JWT_ALG, generateKey(JWT_ALG, JWT_RULE), sub, aud, jti, iss, nbf, duration);
} /**
* 构建JWT
*
* @param sub jwt 面向的用户
* @param jti jwt 唯一身份标识,主要用来作为一次性token,从而回避重放攻击
* @return JWT字符串
*/
public static String buildJWT(String sub, String jti, Integer duration) {
return buildJWT(sub, null, jti, null, null, duration);
} /**
* 构建JWT
* <p>使用 UUID 作为 jti 唯一身份标识</p>
* <p>JWT有效时间 600 秒,即 10 分钟</p>
*
* @param sub jwt 面向的用户
* @return JWT字符串
*/
public static String buildJWT(String sub) {
return buildJWT(sub, null, UUID.randomUUID().toString(), null, null, 600);
} /**
* 解析JWT
*
* @param key jwt 加密密钥
* @param claimsJws jwt 内容文本
* @return {@link Jws}
* @throws Exception
*/
public static Jws<Claims> parseJWT(Key key, String claimsJws) {
// 移除 JWT 前的"Bearer "字符串
claimsJws = StringUtils.substringAfter(claimsJws, JWT_SEPARATOR);
// 解析 JWT 字符串
return Jwts.parser().setSigningKey(key).parseClaimsJws(claimsJws);
} /**
* 校验JWT
*
* @param claimsJws jwt 内容文本
* @return ture or false
*/
public static Boolean checkJWT(String claimsJws) {
boolean flag = false;
try {
SecretKey key = generateKey(JWT_ALG, JWT_RULE);
// 获取 JWT 的 payload 部分
flag = (parseJWT(key, claimsJws).getBody() != null);
} catch (Exception e) {
log.warn("JWT验证出错,错误原因:{}", e.getMessage());
}
return flag;
} /**
* 校验JWT
*
* @param key jwt 加密密钥
* @param claimsJws jwt 内容文本
* @param sub jwt 面向的用户
* @return ture or false
*/
public static Boolean checkJWT(Key key, String claimsJws, String sub) {
boolean flag = false;
try {
// 获取 JWT 的 payload 部分
Claims claims = parseJWT(key, claimsJws).getBody();
// 比对JWT中的 sub 字段
flag = claims.getSubject().equals(sub);
} catch (Exception e) {
log.warn("JWT验证出错,错误原因:{}", e.getMessage());
}
return flag;
} /**
* 校验JWT
*
* @param claimsJws jwt 内容文本
* @param sub jwt 面向的用户
* @return ture or false
*/
public static Boolean checkJWT(String claimsJws, String sub) {
return checkJWT(generateKey(JWT_ALG, JWT_RULE), claimsJws, sub);
}
}

AuthorizationInterceptor.java


package com.app.web.core; import com.app.core.util.JwtUtil;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; /**
* 请求鉴权拦截器
*/
@Log4j2
public class AuthorizationInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
boolean flag = false; // 获取 HTTP HEAD 中的 TOKEN
String authorization = request.getHeader("Authorization");
// 校验 TOKEN
flag = StringUtils.isNotBlank(authorization) ? JwtUtil.checkJWT(authorization) : false;
// 如果校验未通过,返回 401 状态
if (!flag)
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); return flag;
}
}

SON Web Tokens 工具类 [ JwtUtil ]的更多相关文章

  1. web开发工具类

    1.日期工具类 import java.text.SimpleDateFormat; import java.util.Date; public class DateUtil { public sta ...

  2. Web 开发工具类(5) | DateUtils

    日期工具类 import java.text.ParseException; import java.text.ParsePosition; import java.text.SimpleDateFo ...

  3. Web 开发工具类(1): CookieUtils

    CookieUtils 整合了常用的一些对Cookie的相关操作: package com.evan.common.utils; import java.io.UnsupportedEncodingE ...

  4. Web 开发工具类(2): HttpClientUtils

    HttpClientUtils 整合了一些 web开发中常用的httpClient操作: package com.evan.common.utils; import java.io.IOExcepti ...

  5. Web 开发工具类(4): IDUtils

    package com.easybuy.utils; import java.util.Random; /** * * <p>Title: IDUtils</p> * < ...

  6. Web 开发工具类(3): JsonUtils

    JsonUtils 整合了一些对Json的相关操作: package com.evan.common.utils; import java.util.List; import com.fasterxm ...

  7. Spring web 工具类 WebApplicationContextUtils

    概述 Spring web 的工具类 WebApplicationContextUtils 位于包 org.springframework.web.context.support 是访问一个Servl ...

  8. SpringBoot + Vue + ElementUI 实现后台管理系统模板 -- 后端篇(五): 数据表设计、使用 jwt、redis、sms 工具类完善注册登录逻辑

    (1) 相关博文地址: SpringBoot + Vue + ElementUI 实现后台管理系统模板 -- 前端篇(一):搭建基本环境:https://www.cnblogs.com/l-y-h/p ...

  9. SpringMVC 常用工具类与接口

    ClassPathResource 在类路径下读取资源 public final String getPath()public boolean exists()public InputStream g ...

随机推荐

  1. google protocol buffer——protobuf的使用特性及编码原理

    这一系列文章主要是对protocol buffer这种编码格式的使用方式.特点.使用技巧进行说明,并在原生protobuf的基础上进行扩展和优化,使得它能更好地为我们服务. 在上一篇文章中,我们展示了 ...

  2. Trie详解

    Trie,又名字典树.单词查找树,可以较高效地实现统计.排序和保存大量的字符串. 顾名思义,Trie是一个树状的结构,按照树型结构来存储字符串,显然是一种以空间换时间的方法.整体上理解和实现都不会很难 ...

  3. 不要再学 JSP 了,学 SpringBoot + Thymeleaf + Vue吧

    老读者就请肆无忌惮地点赞吧,微信搜索[沉默王二]关注这个在九朝古都洛阳苟且偷生的程序员.本文 GitHub github.com/itwanger 已收录,里面还有我精心为你准备的一线大厂面试题. 读 ...

  4. python IDE(集成开发环境)——PyCharm的安装

    选择PyCharm的原因: 1.很多大佬都推荐,说适合实战操作项目 2.另外是界面可视化不错,颜色很舒服(体验完之后的感觉) 3.PyCharm本身有很多操作快捷键很方便(后续可以记下来常用的,方便自 ...

  5. Ubuntu安装Windows官方版QQ和微信(使用deepin wine)

  6. selenium模拟登录豆瓣和qq空间

    selenium模拟登录豆瓣和qq空间今天又重新学习了下selenium,模拟登录豆瓣,发现设置等待时间真的是很重要的一步,不然一直报错:selenium.common.exceptions.NoSu ...

  7. python3笔记-列表

    列表去重的两种方式: # 创建列表放数据 a =[1,2,1,4,2] b=[1,3,4,3,1,3] d=[] for i in a: if i not in d: d.append(i) prin ...

  8. Easy Game(记忆化搜索)

    You are playing a two player game. Initially there are n integer numbers in an array and player A an ...

  9. [BUUOJ记录] [BJDCTF2020]The mystery of ip

    本题考察XFF头的ssti模板注入,没有过滤,算是入门题 进入题目hint.php的源码中可以看到一个hint 猜测是通过XFF头来获取信息的,发个HTTP请求添加一个XFF头测试一下: GET /f ...

  10. 【Azure DevOps系列】Azure DevOps构建并发布Nuget程序包

    在Azure DevOps中,管道可以用来构建解决方案,O(∩_∩)O哈哈~快万能了,本章主要介绍如何创建Nuget包并且将其发布到Nuget服务器的过程. 前面我创建了一个非常简单的类库,这边我不做 ...