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. 真是没想到 Springboot + Flowable 工作流开发会这么简单

    本文收录在个人博客:www.chengxy-nds.top,技术资料共享,同进步 程序员是块砖,哪里需要哪里搬 公司内部的OA系统最近要升级改造,由于人手不够就把我借调过去了,但说真的我还没做过这方面 ...

  2. C++算法 线段树

    线段树这个算法,看起来非常高端,而且很有用处,所以还是讲一下下吧. 温馨提示:写线段树前请做好写码5分钟,调试一辈子的准备^-^ 啊直接步入正题…… 首先我们考虑一个题目:有一个序列,要做到单点修改单 ...

  3. zero:seo优化的三部曲

    http://www.wocaoseo.com/thread-230-1-1.html 理解用户的需求.了解搜索引擎的原理.明白如何通过搜索引擎优化对网站产生价值,这是SEO学习中应该陆续深入的三个部 ...

  4. 力扣Leetcode 983. 最低票价

    最低票价 在一个火车旅行很受欢迎的国度,你提前一年计划了一些火车旅行.在接下来的一年里,你要旅行的日子将以一个名为 days 的数组给出.每一项是一个从 1 到 365 的整数. 火车票有三种不同的销 ...

  5. 广州做假证c

    广州做假证[电/薇:187ヘ1184ヘ0909同号]办各类证件-办毕业证-办离婚证,办学位证书,办硕士毕业证,办理文凭学历,办资格证,办房产证不. 这是一个简单的取最大值程序,可以用于处理 i32 数 ...

  6. 单元测试框架 python

    1.为什么要做单元测试 单元测试更细致.更有针对性 单元测试能测试到很多系统测试无法达到的测试 单元测试是在编码中做的测试,发现问题方便修改,而系统测试的问题修改成本可能变高 单元测试是自动化测试 2 ...

  7. 被Spring坑了一把,查看源码终于解决了DataFlow部署K8s应用的问题

    1 前言 欢迎访问南瓜慢说 www.pkslow.com获取更多精彩文章! Docker & Kubernetes相关文章:容器技术 基于各种原因,团队的Kubernetes被加了限制,必须在 ...

  8. 会话技术之 Session

    会话技术之 Session 不多废话,先来一个 HelloWorld. Session 有 get 肯定要先有 set . @Override protected void service(HttpS ...

  9. webstorm编写vue、react 将大驼峰组件命名转换成短横杠命名

    大家好!我是木瓜太香,精通 webstorm 与常见前端技术的工程师,偶尔也在b站搞一些 webstorm 技巧教学,今天给大家带来的是大驼峰小驼峰快速转换短横杠命名或者下划线命名的方式. 开发中我们 ...

  10. Java中构建长字符串的四种模式

    回字有四种写法,构建字符串也有四种方式. 用+号最快,第二第三种可读性好,第四种是log4j自有的.下面请见代码: package logbackCfg; import java.text.Messa ...