为什么要告别session?有这样一个场景,系统的数据量达到千万级,需要几台服务器部署,当一个用户在其中一台服务器登录后,用session保存其登录信息,其他服务器怎么知道该用户登录了?(单点登录),当然解决办法有,可以用spring-session。如果该系统同时为移动端服务呢?移动端通过url向后台要数据,如果用session,通过sessionId识别用户,万一sessionId被截获了,别人可以利用sessionId向后台要数据,就有安全隐患了。所以有必要跟session说拜拜了。服务端不需要存储任何用户的信息,用户的验证应该放在客户端,jwt就是这种方式!
什么是jwt?
最详细的是官网:https://jwt.io/
这里以java的ssm框架为例,集成jwt。
1.pom.xml 导入jwt的包
<!-- jwt -->
<!-- https://mvnrepository.com/artifact/com.auth0/java-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;
}
}
}
- 51
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();
}
}
- 73
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;
publicclass ResponseData {privatefinal String message;
privatefinalint code;
privatefinal Map<String, Object> data = new HashMap<String, Object>();
public String getMessage() {
return message;
}
publicintgetCode() {
return code;
}
public Map<String, Object> getData() {
return data;
}
public ResponseData putDataValue(String key, Object value) {
data.put(key, value);
returnthis;
}
privateResponseData(int code, String message) {
this.code = code;
this.message = message;
}
publicstatic ResponseData ok() {
returnnew ResponseData(200, "Ok");
}
publicstatic ResponseData notFound() {
returnnew ResponseData(404, "Not Found");
}
publicstatic ResponseData badRequest() {
returnnew ResponseData(400, "Bad Request");
}
publicstatic ResponseData forbidden() {
returnnew ResponseData(403, "Forbidden");
}
publicstatic ResponseData unauthorized() {
returnnew ResponseData(401, "unauthorized");
}
publicstatic ResponseData serverInternalError() {
returnnew ResponseData(500, "Server Internal Error");
}
publicstatic ResponseData customerError() {
returnnew ResponseData(1001, "customer Error");
}
}
http://blog.csdn.net/change_on/article/details/71191894
相关推荐
本篇文章将详细探讨如何将SpringSecurity与JWT相结合,实现高效且安全的身份验证。 首先,让我们了解一下SpringSecurity的基本配置。在SpringSecurity中,我们通常会创建一个`WebSecurityConfigurerAdapter`的子类...
在本教程中,我们将深入探讨如何将Swagger2与Spring Boot集成,同时考虑到Spring Security和JWT(JSON Web Token)的安全机制。Swagger2是一个流行的API文档工具,它允许开发者以交互式方式展示和测试RESTful API。...
在Spring Boot项目中,我们可以使用Spring Security的JWT扩展来实现登录验证和令牌管理。 项目的实施步骤可能包括以下几个关键部分: 1. **项目初始化**:使用Spring Initializr创建一个新的Spring Boot项目,添加...
**Spring Boot整合JWT详解** Spring Boot作为Java领域中流行的微服务框架,因其便捷的配置和快速的开发...通过这个项目,你不仅可以掌握Spring Boot和Spring Security的使用,还能深入了解JWT在实际应用中的实现方式。
Spring Boot JWT(JSON Web Token)Demo是一个基于Spring Boot框架的简单应用,用于演示JWT技术在身份验证和授权中的应用。JWT是一种轻量级的身份验证标准,广泛应用于现代Web应用程序,尤其是微服务架构中。在这个...
SpringBoot+SpringSecurity+JWT+MybatisPlus实现基于注解的权限验证,可根据注解的格式不同,做到角色权限控制,角色加资源权限控制等,粒度比较细化。 @PreAuthorize("hasAnyRole('ADMIN','USER')"):具有admin或...
用户通过API接口进行登录,Spring Security验证用户信息并生成JWT,然后将令牌存储在Redis中。之后,每次API请求都会携带JWT,Redis和Spring Security共同完成身份验证,MyBatis则负责与MySQL数据库的交互,实现数据...
在本文中,我们将深入探讨如何在SpringBoot应用中集成Spring Security进行登录管理,并实现session共享。这是一项关键的安全措施,可以确保用户会话在多个微服务之间的一致性。我们将基于给定的标签——SpringBoot、...
编译器版本:IntelliJ IDEA 2020.3.2 x64 JDK版本:java 1.8.0_111 SpringBoot集成JWT快速入门Demo,演示jwt生成与验证等功能,可以通过swaggler或者Postman进行测试。
本篇文章将深入探讨如何在Spring Cloud项目中整合OAuth2和JWT,以及与MyBatis的集成。 首先,OAuth2是一个开放标准,主要用于授权。它允许第三方应用在用户许可的情况下访问其私有资源,而无需获取用户的用户名和...
在这个项目中,Spring Security会被配置为使用JWT进行身份验证。首先,我们需要创建一个自定义的`AuthenticationProvider`,负责验证用户的凭证。接着,当用户成功登录后,我们将在`AuthenticationSuccessHandler`中...
yshop基于当前流行技术组合的前后端分离商城系统: SpringBoot2+MybatisPlus+SpringSecurity+jwt+redis+Vue的前后端分离的商城系统, 包含分类、sku、运费模板、素材库、小程序直播、拼团、砍价、商户管理、 秒杀、...
在Spring Boot中集成JWT,我们需要创建一个TokenProvider类,负责生成和验证JWT。这个类通常会包含`generateToken`和`validateToken`方法。生成的JWT可以包含用户信息,如用户名、角色等,以便后端在验证时进行权限...
接下来,我们将步骤化讲解如何在Spring Boot 3.x与Spring Security的集成中使用JWT: 1. **项目初始化**: - 创建一个新的Spring Boot项目,选择Spring Web和Spring Security starter。 - 添加JWT相关的依赖,如`...
总结来说,Spring Boot集成JWT实现token验证的过程包括引入依赖、配置Spring Security、创建自定义过滤器以及编写Token生成和验证逻辑。这种方式不仅提高了安全性,还减少了服务器的负担,因为不再需要管理用户的...
SpringBoot集成JWT实现token验证源码.zip SpringBoot集成JWT实现token验证源码.zip SpringBoot集成JWT实现token验证源码.zip 【备注】 主要针对计算机相关专业的正在做毕设的学生和需要项目实战的Java学习者。 也可...
Spring Security 是一个强大的...这个项目应该包含了一个运行的示例,展示了如何将Spring Security与JWT集成,实现服务鉴权访问。开发者可以通过研究源代码,了解具体的实现细节,学习如何在自己的项目中应用这些技术。
在SpringSecurity中,我们可以集成JWT来实现无状态的身份验证。用户登录后,服务器返回JWT,客户端保存该令牌,并在后续请求中携带,服务器通过验证JWT的签名确认用户身份。 3. **MyBatis**:MyBatis消除了几乎所有...
Spring Boot 提供了一个 spring-security-jwt 模块,用于生成和验证 JWT。 在使用 Spring Boot 集成 OAuth2 授权框架时,我们需要注意以下几点: * 需要正确地配置授权服务器和资源服务器 * 需要正确地实现身份...
赠送jar包:spring-security-jwt-1.0.10.RELEASE.jar; 赠送原API文档:spring-security-jwt-1.0.10.RELEASE-javadoc.jar; 赠送源代码:spring-security-jwt-1.0.10.RELEASE-sources.jar; 赠送Maven依赖信息文件:...