SpringBoot 实现登录功能
目录
- 下发JWT 令牌
- 依赖文件
- 令牌生成
- 令牌验证
- 统一验证技术
- 过滤器 Filter
- 快速使用
- 实现登录校验
- 拦截器 Interceptor
- 快速使用
- 实现登录校验
下发JWT 令牌
全称: JSON Web Token
官网: https://jwt.io/
以JSON 的数据格式安全传输信息,利用 base64 进行编码。
组成:
第一部分:Header (头),记录 签名算法 ,令牌类型 。
例如:{“alg”: “HS256”,“type”: “JWT”}
第二部分:Payload (有效载荷),携带自定义信息 ,一般为登录 账号 和 密码。
第三部分:Signature 防止 被篡改 将 header,payload,并加入指定密钥,通过指定签名算法计算而来。
依赖文件
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!-- java 9 以上需要引入 -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.1</version>
</dependency>
令牌生成
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("name", "lisi");
hashMap.put("password", "1234");
String jwt = Jwts.builder()
/*sign 签名算法*/.signWith(SignatureAlgorithm.HS256, "ssstfthm") //sign 签名算法
/* 自定义内容 */ .setClaims(hashMap) // 自定以内容
/*过期时间*/ .setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000))
.compact(); //生成令牌
System.out.println(jwt);
令牌验证
Claims :可以像遍历一个 Map 一样遍历 Claims 对象中的所有声明。例如,可以使用 for (Map.Entry<String, Object> entry : claims.entrySet()) 来遍历所有声明,并访问它们的键和值。
String token = "eyJhbGciOiJIUzI1NiJ9.eyJwYXNzd29yZCI6IjEyMzQiLCJuYW1lIjoibGlzaSIsImV4cCI6MTczNTQ4NzczMH0.JnQhXvsx0ZOsrPrtrUmkZ-RLCaVgwP8dgrS6nArF-vQ";
Claims claims = Jwts.parser()
.setSigningKey("ssstfthm") //设置签名
.parseClaimsJws(token) //令牌内容
.getBody();
System.out.println(claims);
统一验证技术
过滤器 Filter
JavaWeb 三大组件之一 (Servlet , Filter ,Listener) 之一
一般完成 通用的操作,比如:登录校验,统一编码,敏感字符处理
快速使用
多个 过滤器 按类名排序
1.创建过滤器类
javax.servlet.Filter
@WebFilter(urlPatterns = "/*") //配置拦截路径
public class FilterDemo implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("过滤器创建");
Filter.super.init(filterConfig);
}
@Override
public void destroy() {
System.out.println("过滤器销毁");
Filter.super.destroy();
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("过滤器 拦截");
// 放行操作
filterChain.doFilter(servletRequest,servletResponse);
}
}
- 在启动类中添加 @ServletComponentScan
org.springframework.boot.web.servlet.ServletComponentScan;
实现登录校验
@WebFilter(urlPatterns = "/*")
public class FilterDemo implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 1. 获取请求头
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String url=request.getRequestURI();
//2. 是登录请求直接放行
if (url.contains("/login")) {
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("登录操作合法");
return;
}
//3. 获取请求头的令牌
String jwt=request.getHeader("token");
// 4.判断令牌是否存在,不存在返回错误
if (!StringUtils.hasLength(jwt)) {
//没有令牌 返回错误
Result result=new Result(0,"NOT_LOGIN",null);
// 手动转化 对象 --》json 阿里巴巴 fastjson
String notlogin= JSONObject.toJSONString(result);
response.getWriter().write(notlogin);
return;
}
//5.解析token,解析失败返回错误结果
try {
JwtUtils.parseJWT(jwt);
} catch (Exception e) {
Result result=new Result(0,"NOT_LOGIN",null);
String notlogin= JSONObject.toJSONString(result);
response.getWriter().write(notlogin);
return;
}
//6. 放行
filterChain.doFilter(servletRequest,servletResponse);
}
}
拦截器 Interceptor
概念:是一种动态拦截方法调用的机制,类似于过滤器。Spring 框架中提供。
快速使用
1.定义拦截器,实现 HandlerInterfaceptor 接口
@Component //交给IOC容器管理
public class LoginInterceptor implements HandlerInterceptor {
@Override //目标资源方法 运行前运行, 返回 true 放行 false,不放行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return HandlerInterceptor.super.preHandle(request, response, handler);
}
@Override // 运行后进行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override // 最后运行
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
- 定义配置类
拦截路径:
拦截路径 | 含义 |
---|---|
/* | 一级路径 |
/** | 任意路径 |
/depts/* | depts 下的一级路径 |
/depts/* | depts 下的任意级路径 |
.excludePathPatterns(“/login”) 不需要拦截的资源
@Configuration //配置类注解
public class WebConfig implements WebMvcConfigurer {
@Autowired
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor).addPathPatterns("/**");
}
}
实现登录校验
public class LoginInterceptor implements HandlerInterceptor {
@Override //目标资源方法 运行前运行, 返回 true 放行 false,不放行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("拦截器Q");
String token=request.getHeader("token");
if (!StringUtils.hasLength(token)) {
//没有令牌 返回错误
Result result=new Result(0,"NOT_LOGIN",null);
// 手动转化 对象 --》json 阿里巴巴 fastjson
String notlogin= JSONObject.toJSONString(result);
response.getWriter().write(notlogin);
return false;
}
try {
JwtUtils.parseJWT(token);
}catch (Exception e){
String notlogin=JSONObject.toJSONString(new Result(0,"NOT_LOGIN",null));
response.getWriter().write(notlogin);
return false;
}
return true;
}
}