最开始未分前后端分离的时候,用户权限是通过session保存的。前后端分离以后需要一个媒介来标识用户状态,就产生了token。JWT技术主要封装了用于用户登录鉴权的基本功能
Session:在计算机中,尤其是在网络应用中,称为“会话控制”。Session对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的Web页之间跳转时,存储在Session对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web页时,如果该用户还没有会话,则Web服务器将自动创建一个 Session对象。当会话过期或被放弃后,服务器将终止该会话。Session 对象最常见的一个用法就是存储用户的首选项。例如,如果用户指明不喜欢查看图形,就可以将该信息存储在Session对象中。有关使用Session 对象的详细信息,请参阅“ASP应用程序”部分的“管理会话”。注意会话状态仅在支持cookie的浏览器中保留。
Token在计算机身份认证中是令牌(临时)的意思,在词法分析中是标记的意思。一般作为邀请、登录系统使用。
如果非分布式一般保存在本地全局变量集合中,或者保存到redis中。分布式的话就只能保存到redis,否则其他服务无法获取。
JWT(全称:Json Web Token)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。
JWT由3部分组成:标头(Header)、有效载荷(Payload)和签名(Signature)
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwiZXhwIjoxNjUzODA5MTc3fQ.WZr_z0XCZdm_G9oc_HD-YT2xF0dKyy8257T_2Tk4130
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9. //标头(Header)
eyJzdWIiOiIxIiwiZXhwIjoxNjUzODA5MTc3fQ. //有效载荷(Payload)
WZr_z0XCZdm_G9oc_HD-YT2xF0dKyy8257T_2Tk4130 //签名(Signature)
Base64(Header).Base64(Payload).HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),secret)
有效载荷(Payload) 一般可以存储用户基本信息用于业务操作。
搭建springboot
从spring boot到spring cloud(二)JAVA入门教学,搭建基本的springboot_lzy711的博客-CSDN博客
可以查看过去的文章。
maven文件
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.5.7
com.aqjyxt
aqjyxt
0.0.1-SNAPSHOT
aqjyxt
Demo project for Spring Boot
1.8
org.springframework.boot
spring-boot-starter-web
com.alibaba
druid-spring-boot-starter
1.1.10
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.2.2
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-web
io.springfox
springfox-boot-starter
3.0.0
com.github.xiaoymin
swagger-bootstrap-ui
1.9.6
mysql
mysql-connector-java
runtime
org.springframework.boot
spring-boot-starter-test
test
com.auth0
java-jwt
3.4.0
org.springframework.boot
spring-boot-maven-plugin
主要是导入JWT
编写JWT工具类
package com.aqjyxt.bean;
import com.alibaba.druid.util.StringUtils;
import com.aqjyxt.entity.aqjyxt_user;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.util.Calendar;
import javax.xml.bind.DatatypeConverter;
/**
* @author admin
*/
public class JWTUtils {
//解析token的秘钥
public static String password = "admin123";
/**
* 获取token
* @param u user
* @return token
*/
public static String getToken(aqjyxt_user u) {
Calendar instance = Calendar.getInstance();
//默认令牌过期时间7天
instance.add(Calendar.DATE, 7);
//把用户id保存到subject变量,也可以使用.withClaim("userId", 123)
JWTCreator.Builder builder = JWT.create();
builder.withSubject(u.getId());
return builder.withExpiresAt(instance.getTime())
.sign(Algorithm.HMAC256(password));
}
/**
* 验证token合法性 成功返回token
*/
public static DecodedJWT verify(String token){
return JWT.require(Algorithm.HMAC256(password)).build().verify(token);
}
/**
* 解析Jwt字符串
*
* @param jwt Jwt字符串
* @return Claims 解析后的对象
*/
public static String parseJWT(String token) {
return JWT.require(Algorithm.HMAC256(password)).build().verify(token).getClaim("userId").asString();
}
}
DecodedJWT jwt = JWT.decode(request.getHeader("token"));
System.out.println(jwt.getSubject()+"----------");
以上代码是JWT解析获取用户ID
编写JWT拦截器和JWT过滤器
package com.aqjyxt.Interceptor;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.aqjyxt.bean.JWTUtils;
import com.aqjyxt.bean.Returnben;
import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JWTInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Returnben returnben = new Returnben();
//获取请求头中的令牌
String token = request.getHeader("token");
try {
//验证令牌
DecodedJWT verify = JWTUtils.verify(token);
return true;
} catch (SignatureVerificationException e){
e.printStackTrace();
returnben.setMsg("无效签名");
returnben.setSuccess("10001");
} catch (TokenExpiredException e){
e.printStackTrace();
returnben.setMsg("token过期");
returnben.setSuccess("10002");
} catch (AlgorithmMismatchException e){
e.printStackTrace();
//token算法不一致
returnben.setMsg("无效签名");
returnben.setSuccess("10001");
} catch (Exception e){
e.printStackTrace();
returnben.setMsg("token无效");
returnben.setSuccess("10003");
}
//将map转为json
String json = new ObjectMapper().writeValueAsString(returnben);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(json);
return false;
}
}
package com.aqjyxt.Interceptor;
import java.util.ArrayList;
import java.util.List;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 注册拦截器
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//下面list是放行swagger
List l=new ArrayList();
l.add("/login");
l.add("/logout");
l.add("/css/**");
l.add("/js/**");
l.add("/index.html");
l.add("favicon.ico");
l.add("/doc.html");
l.add("/webjars/**");
l.add("/swagger-resources/**");
l.add("/v2/api-docs/**");
registry.addInterceptor(new JWTInterceptor())
//拦截 把需要拦截的请求配置
.addPathPatterns("/systempc/*")
//放行
.excludePathPatterns("/user/login")
.excludePathPatterns(l);
}
}
登录返回token
package com.aqjyxt.entity;
public class aqjyxt_user {
private String id;
private String user;
private String password;
private String username;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id == null ? null : id.trim();
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user == null ? null : user.trim();
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password == null ? null : password.trim();
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username == null ? null : username.trim();
}
}
@RequestMapping(value="/login",method = RequestMethod.POST)
@ResponseBody
@ApiOperation("登录接口")
public Returnben login(HttpServletRequest request, HttpSession session,aqjyxt_user aqjyxt_user) {
Returnben returnben = new Returnben();
String token = JWTUtils.getToken(aqjyxt_user);
returnben.setData(token);
returnben.setMsg("成功");
returnben.setSuccess("0");
return returnben;
}