JWT的工具类 加密解密工具

package top.wintp.crud.util;

import com.auth0.jwt.JWTSigner;
import com.auth0.jwt.JWTVerifier;
import com.fasterxml.jackson.databind.ObjectMapper; import java.util.HashMap;
import java.util.Map; /**
* @description: description: JWT的工具类
* <p>
* @author: pyfysf
* <p>
* @qq: 337081267
* <p>
* @CSDN: http://blog.csdn.net/pyfysf
* <p>
* @blog: http://wintp.top
* <p>
* @email: pyfysf@163.com
* <p>
* @time: 2018/11/16
*/
public class JWTUtils {
private static final String SECRET = "XX#$%()(#*!()!KLPYFYSFWINTOP WT>DFklsfajd f>?DFDSfWINTPT>Dasgdls.topwintp.stopxafkdlspyfysfW"; private static final String EXP = "exp"; private static final String PAYLOAD = "payload"; //加密,传入一个对象和有效期
public static <T> String sign(T object, long maxAge) {
try {
final JWTSigner signer = new JWTSigner(SECRET);
final Map<String, Object> claims = new HashMap<String, Object>();
ObjectMapper mapper = new ObjectMapper();
String jsonString = mapper.writeValueAsString(object);
claims.put(PAYLOAD, jsonString);
claims.put(EXP, System.currentTimeMillis() + maxAge);
return signer.sign(claims);
} catch (Exception e) {
return null;
}
} //解密,传入一个加密后的 token字符串和解密后的类型
public static <T> T unsign(String jwt, Class<T> classT) {
final JWTVerifier verifier = new JWTVerifier(SECRET);
try {
final Map<String, Object> claims = verifier.verify(jwt);
if (claims.containsKey(EXP) && claims.containsKey(PAYLOAD)) {
long exp = (Long) claims.get(EXP);
long currentTimeMillis = System.currentTimeMillis();
if (exp > currentTimeMillis) {
String json = (String) claims.get(PAYLOAD);
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(json, classT);
}
}
return null;
} catch (Exception e) {
return null;
}
} }

登录的接口


@RequestMapping("/login")
@ResponseBody
public Map<String, Object> login(User user) {
logger.info("LoginController login() username " + user.getUsername());
logger.info("LoginController login() password " + user.getPassword());
Map<String, Object> resultMap = new HashMap<>(); //先到数据库验证 用户名密码
//Integer loginId = userService.checkLogin(login);
Integer loginId = 1;
if (null != loginId) {
//User user = userService.getUserByLoginId(loginId);
user.setId(loginId);
//login.setId(loginId);
//给用户jwt加密生成token
String token = JWTUtils.sign(user, 100000L);
//封装成对象返回给客户端
resultMap.put("loginId", user.getId());
resultMap.put("token", token);
//responseData.putDataValue("loginId", login.getId());
//responseData.putDataValue("token", token);
//responseData.putDataValue("user", user);
} else {
//responseData = ResponseData.customerError();
} return resultMap;
}

拦截器

package top.wintp.crud.interceptors;

import com.auth0.jwt.internal.org.bouncycastle.asn1.ocsp.ResponseData;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView; import java.io.PrintWriter; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import top.wintp.crud.entity.User;
import top.wintp.crud.util.JWTUtils; /**
* @description: description: 登录的拦截器
* <p>
* @author: pyfysf
* <p>
* @qq: 337081267
* <p>
* @CSDN: http://blog.csdn.net/pyfysf
* <p>
* @blog: http://wintp.top
* <p>
* @email: pyfysf@163.com
* <p>
* @time: 2018/11/19
*/
public class LoginInterceptor implements HandlerInterceptor {
private static Logger logger = LoggerFactory.getLogger(LoginInterceptor.class); @Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception arg3) throws Exception {
} @Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView model) throws Exception {
} //拦截每个请求
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
response.setCharacterEncoding("utf-8");
String token = request.getParameter("token");
//token不存在
if (null != token) {
User login = JWTUtils.unsign(token, User.class);
String loginId = request.getParameter("loginId");
//解密token后的loginId与用户传来的loginId不一致,一般都是token过期
if (null != loginId && null != login) {
if (Integer.parseInt(loginId) == login.getId()) {
logger.info("LoginInterceptor preHandle() 成功 "); return true;
} else { logger.info("LoginInterceptor preHandle() 失败 "); response.sendRedirect("/login/index.do");
return false;
}
} else { logger.info("LoginInterceptor preHandle() 失败 "); response.sendRedirect("/login/index.do");
return false;
}
} else {
logger.info("LoginInterceptor preHandle() 失败 ");
response.sendRedirect("/login/index.do");
return false;
}
}
}

博客参考:

https://www.jianshu.com/p/576dbf44b2ae

https://www.jianshu.com/p/a12fc67c9e05

https://blog.csdn.net/change_on/article/details/71191894

JWT 生成的TOKEN 生成规则

JWT详解

JWT由三个部分组成分别是header、payload、signature用.连接,如:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiJ9.d1bf66192c1bff9038bcd212ba05dfde55c40d4e2254dd99c9c7653dd27c39ba

header:

{
"typ": "JWT",
"alg": "HS256"
}

typ: 类型,alg: 加密算法

将上面的json内容Base64之后就形成了JWT的第一部分

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

payload:

{
"id": 1,
"username": "admin"
}

这部分为用户自定义内容(不要存放敏感信息)

将上面的json内容Base64之后就形成了JWT的第二部分

eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiJ9

signature:

第三部分为第一部分和第二部分的签名

let headerBase64 = new Buffer(JSON.stringify(header)).toString('base64');
let payloadBase64 = new Buffer(JSON.stringify(payload)).toString('base64');
let sha256 = crypto.createHmac('sha256', 'your salt');
sha256.update(headerBase64 + '.' + payloadBase64);
let sign = sha256.digest('hex');
let finalJwtString = headerBase64 + '.' + payloadBase64 + '.' + sign;

总结

优点

因为json的通用性,所以JWT是可以进行跨语言支持的,像JAVA,JavaScript,NodeJS,PHP等很多语言都可以使用。

因为有了payload部分,所以JWT可以在自身存储一些其他业务逻辑所必要的非敏感信息。

便于传输,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的。

它不需要在服务端保存会话信息, 所以它易于应用的扩展

安全相关

1.不应该在jwt的payload部分存放敏感信息,因为该部分是客户端可解密的部分。

2.保护好secret私钥,该私钥非常重要。

3.如果可以,请使用https协议

最新文章

  1. 使用Navicat远程管理OpenShift的数据库
  2. swift复合类型
  3. 登录界面 beta版
  4. UI:字典的两种取值的区别
  5. LeetCode_Length of Last Word
  6. asp.net页面生命周期回顾
  7. 2017-4-24 WinForm开发基础、窗体的属性CenterScreen
  8. TestNG教程网站
  9. OSPFv3实验配置(GNS3)
  10. Maven 项目 启动时 解决3 字节的 UTF-8 序列的字节 3 无效
  11. 2018-11-13 中文代码示例之Programming in Scala学习笔记第二三章
  12. Spring Security(二十六):8. Spring Security Community
  13. 九、xadmin菜单分组管理
  14. hdu-6166(最短路+二进制分组)
  15. std::lock_guard/std::unique_lock
  16. 关于Excel导出实例(适合新手,比较详细)
  17. 【Codeforces 1132E】Knapsack
  18. JAVA声明一个对象数组
  19. BZOJ 2427 [HAOI2010]软件安装 | 这道树形背包裸题严谨地证明了我的菜
  20. thinkphp中order方法

热门文章

  1. delphi常用正则表达式
  2. MySQL InnoDB缓冲池(Buffer Pool)
  3. Windows 各种计时函数总结(QueryPerformanceCounter可以达到微秒)
  4. Java基础(五) final关键字浅析
  5. JavaScript规定了几种语言类型?
  6. React躬行记(5)——React和DOM
  7. 一文详解 LVS、Nginx 及 HAProxy 工作原理( 附大图 )
  8. 实现h5公众号分享功能(vue项目也适用)
  9. laravel中的构造函数依赖注入理解
  10. sort和sorted深入理解----引子:多维列表,如何实现第一个元素升序,第二个元素降序