SpringMVC 集成 JWT验证方式
JWT官网: https://jwt.io/
这里以java的ssm框架为例,集成jwt。
1.pom.xml 导入jwt的包
<!-- jwt -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>2.2.0</version>
</dependency>
2.编写jwt的工具类,包含加密解密功能
import com.auth0.jwt.JWTSigner;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.internal.com.fasterxml.jackson.databind.ObjectMapper; import java.util.HashMap;
import java.util.Map; public class JWT {
private static final String SECRET = "XX#$%()(#*!()!KL<><MQLMNQNQJQK sdfkjsdrow32234545fdf>?N<:{LWPW"; 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;
}
}
}
3.jwt有了,ssm要如何去利用,用户验证的第一步是登录,登录时根据用户传来的username和password到数据库验证身份,如果合法,便给该用户jwt加密生成token
//处理登录
@RequestMapping(value="login", produces = "application/json; charset=utf-8")
public @ResponseBody ResponseData login(HttpServletRequest request, @RequestParam( "email") String email,
@RequestParam("password") String password) {
Login login = new Login();
login.setEmail(email);
login.setPassword(password);
ResponseData responseData = ResponseData.ok();
//先到数据库验证
Integer loginId = userService.checkLogin(login);
if(null != loginId) {
User user = userService.getUserByLoginId(loginId);
login.setId(loginId);
//给用户jwt加密生成token
String token = JWT.sign(login, 60L* 1000L* 30L);
//封装成对象返回给客户端
responseData.putDataValue("loginId", login.getId());
responseData.putDataValue("token", token);
responseData.putDataValue("user", user);
}
else{
responseData = ResponseData.customerError();
}
return responseData;
}
4.在用户登录时,把loginId和token返回给前台,以后用户每次请求时,都得带上这两个参数,后台拿到token后解密出loginId,与用户传递过来的loginId比较,如果相同,则说明用户身份合法。因为是每个登录过后的每个请求,这里用springmvc的拦截器做
<mvc:interceptors>
<mvc:interceptor>
<!-- 匹配的是url路径, 如果不配置或/**,将拦截所有的Controller -->
<mvc:mapping path="/**" />
<!-- /register 和 /login 不需要拦截-->
<mvc:exclude-mapping path="/register" />
<mvc:exclude-mapping path="/login" />
<bean class="com.xforce.charles.interceptor.TokenInterceptor"></bean>
</mvc:interceptor>
<!-- 当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法 -->
</mvc:interceptors>
5.拦截器代码
import java.io.PrintWriter; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView; import com.alibaba.fastjson.JSONObject;
import com.xforce.charles.model.Admin;
import com.xforce.charles.model.Login;
import com.xforce.charles.util.JWT;
import com.xforce.charles.util.ResponseData; public class TokenInterceptor implements HandlerInterceptor{ public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception arg3)
throws Exception {
} public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView model) throws Exception {
} //拦截每个请求
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
response.setCharacterEncoding("utf-8");
String token = request.getParameter("token");
ResponseData responseData = ResponseData.ok();
//token不存在
if(null != token) {
Login login = JWT.unsign(token, Login.class);
String loginId = request.getParameter("loginId");
//解密token后的loginId与用户传来的loginId不一致,一般都是token过期
if(null != loginId && null != login) {
if(Integer.parseInt(loginId) == login.getId()) {
return true;
} else {
responseData = ResponseData.forbidden();
responseMessage(response, response.getWriter(), responseData);
return false;
}
} else {
responseData = ResponseData.forbidden();
responseMessage(response, response.getWriter(), responseData);
return false;
}
} else {
responseData = ResponseData.forbidden();
responseMessage(response, response.getWriter(), responseData);
return false;
}
} //请求不通过,返回错误信息给客户端
private void responseMessage(HttpServletResponse response, PrintWriter out, ResponseData responseData) {
responseData = ResponseData.forbidden();
response.setContentType("application/json; charset=utf-8");
String json = JSONObject.toJSONString(responseData);
out.print(json);
out.flush();
out.close();
} }
6.注意点:用@ResponseBody返回json数据时,有时会有乱码,需要在springmvc的配置文件里面加以下配置(spring4以上)
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes" value = "text/plain;charset=UTF-8" />
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
7.最后分享一个类,用于返回给客户端的万能类,我觉得它可以满足一般的接口
import java.util.HashMap;
import java.util.Map; public class ResponseData { private final String message;
private final int code;
private final Map<String, Object> data = new HashMap<String, Object>(); public String getMessage() {
return message;
} public int getCode() {
return code;
} public Map<String, Object> getData() {
return data;
} public ResponseData putDataValue(String key, Object value) {
data.put(key, value);
return this;
} private ResponseData(int code, String message) {
this.code = code;
this.message = message;
} public static ResponseData ok() {
return new ResponseData(200, "Ok");
} public static ResponseData notFound() {
return new ResponseData(404, "Not Found");
} public static ResponseData badRequest() {
return new ResponseData(400, "Bad Request");
} public static ResponseData forbidden() {
return new ResponseData(403, "Forbidden");
} public static ResponseData unauthorized() {
return new ResponseData(401, "unauthorized");
} public static ResponseData serverInternalError() {
return new ResponseData(500, "Server Internal Error");
} public static ResponseData customerError() {
return new ResponseData(1001, "customer Error");
}
}
SpringMVC 集成 JWT验证方式的更多相关文章
- spring集成jwt验证方式,token验证
为什么要告别session?有这样一个场景,系统的数据量达到千万级,需要几台服务器部署,当一个用户在其中一台服务器登录后,用session保存其登录信息,其他服务器怎么知道该用户登录了?(单点登录), ...
- windows集成身份验证
集成windows身份验证 这种验证方式里面也分为两种情况 NTLM验证 这种验证方式需要把用户的用户名和密码传送到服务端,服务端验证用户名和密码是否和服务器的此用户的密码一致.用户名用明码传送,但是 ...
- Spring Cloud系列-Zuul网关集成JWT身份验证
前言 这两三年项目中一直在使用比较流行的spring cloud框架,也算有一定积累,打算有时间就整理一些干货与大家分享. 本次分享zuul网关集成jwt身份验证 业务背景 项目开发少不了身份认证,j ...
- spring+springMVC集成(annotation方式)
spring+springMVC集成(annotation方式) SpringMVC+Spring4.0+Hibernate 简单的整合 MyBatis3整合Spring3.SpringMVC3
- jwt验证登录信息
为什么要告别session?有这样一个场景,系统的数据量达到千万级,需要几台服务器部署,当一个用户在其中一台服务器登录后,用session保存其登录信息,其他服务器怎么知道该用户登录了?(单点登录), ...
- 如何简单的在 ASP.NET Core 中集成 JWT 认证?
前情提要:ASP.NET Core 使用 JWT 搭建分布式无状态身份验证系统 文章超长预警(1万字以上),不想看全部实现过程的同学可以直接跳转到末尾查看成果或者一键安装相关的 nuget 包 自上一 ...
- asp.net core 集成JWT(一)
[什么是JWT] JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案. JWT的官网地址:https://jwt.io/ 通俗地来讲,JWT是能代表用户身份的令牌,可以使用JWT ...
- asp.net core 集成JWT(二)token的强制失效,基于策略模式细化api权限
[前言] 上一篇我们介绍了什么是JWT,以及如何在asp.net core api项目中集成JWT权限认证.传送门:https://www.cnblogs.com/7tiny/p/11012035.h ...
- 10分钟简单学习net core集成jwt权限认证,快速接入项目落地使用
什么是JWT JSON Web Token(JWT)是目前最流行的跨域身份验证.分布式登录.单点登录等解决方案. JWT的官网地址:https://jwt.io/ 通俗地来讲,JWT是能代表用户身份的 ...
随机推荐
- 数据可视化之powerBI基础(十)快速度量值,帮你更快的进行数据分析
https://zhuanlan.zhihu.com/p/64414831 刚开始学习PowerBI,最头疼的可能就是度量值了,毕竟用了Excel这么多年,只相信自己眼睛看到的,对于这个"虚 ...
- Python函数02/函数的动态参数/函数的注释/名称空间/函数的嵌套/global以及nolocal的用法
Python函数02/函数的动态参数/函数的注释/名称空间/函数的嵌套/global以及nolocal的用法 目录 Python函数02/函数的动态参数/函数的注释/名称空间/函数的嵌套/global ...
- 《Head First 设计模式》:装饰者模式
正文 一.定义 装饰者模式动态地将责任(功能)附加到对象上.若要扩展功能,装饰者提供了比继承更有弹性的替代方案. 要点: 装饰者和被装饰者有相同的超类型. 可以用一个或多个装饰者包装一个对象. 既然装 ...
- 手写简易SpringMVC
手写简易SpringMVC 手写系列框架代码基于普通Maven构建,因此在手写SpringMVC的过程中,需要手动的集成Tomcat容器 必备知识: Servlet相关理解和使用,Maven,Java ...
- C#/VB.NET 在Word中添加条码、二维码
本文介绍如何通过C# 和VB.NET代码实现在Word文档中添加条码和二维码.代码中将分为在Word正文段落中.页眉页脚中等情况来添加. 使用工具:Free Spire.Office for .NET ...
- 测试人员应该掌握的oracle知识体系
闲来无事,总结了一下,软件测试人员应该掌握的基本的oracle数据库知识体系 1.安装 1.1 oracle安装 1.2 oracle升级 1.3 oracle补丁 2.管理 2.1数据库创建(dbc ...
- 少儿编程:python趣味编程第一课
本文仅针对8-16岁的青少年,所以流程是按如何去教好中小学生走的,并不适合成人找工作学习,因为进度也是按照青少年走的 大家好,我是C大叔,从事少儿编程行业三年有余(2016年从事少儿编程行业,少儿编程 ...
- 学Python入门应该先学什么?看完本文你就知道了
学Python应先从Python开发基础部分入手:1.如学习Python语言介绍2.环境安装3.Python基本语法4.基本数据类型5.二进制运算6.来流程控制.7.字符编码.文件处理8.数据类型9. ...
- 快速配置webpack+vue项目
第一步:初始化项目 1.npm init 2. package name: (webpack+vue) webpackvue version: (1.0.0) description: this is ...
- etcd3.0集群安装
etcd 是一个分布式一致性键值存储,用于共享配置和服务发现,Go编写,并使用 Raft 一致性算法来管理高可用复制日志. 特性 简单:支持curl方式的用户API(http+json)安全:可选ss ...