目录
[1. 在config层设置拦截器](#1. 在config层设置拦截器)
[2. 实现LoginInterceptor拦截器](#2. 实现LoginInterceptor拦截器)
[3. 创建JWT工具类](#3. 创建JWT工具类)
[4. 在登录时创建JWT并存入Cookie](#4. 在登录时创建JWT并存入Cookie)
[1. 添加JWT依赖](#1. 添加JWT依赖)
[2. 配置JWT环境](#2. 配置JWT环境)
本篇博客将为大家介绍了如何在Spring Boot应用中实现基于JWT的登录拦截器,以保证未登录用户无法访问指定的页面。
一、配置拦截器进行登录校验
1. 在config
层设置拦截器
我们首先在config
层创建一个配置类,用来设置需要拦截的页面。在Spring Boot中,我们可以通过实现WebMvcConfigurer
接口来配置拦截器。
创建LoginConfig类:
java
import com.bim.bimbookshop.interceptor.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
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 LoginConfig implements WebMvcConfigurer {
@Autowired
private LoginInterceptor loginInterceptor;
/**
* 配置拦截器
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor) // 添加拦截器
.addPathPatterns("/**") // 配置拦截路径
.excludePathPatterns("/login/**", "/static/**", "/templates/**"); // 配置排除路径
}
}
这里的addPathPatterns("/**")
表示拦截所有路径,而excludePathPatterns
用于排除登录、注册等静态资源的路径。例如,/login/**
表示排除所有与登录相关的请求。
2. 实现LoginInterceptor
拦截器
接下来,我们需要在interceptor
层创建一个拦截器类,用来判断用户是否已登录。
创建LoginInterceptor类:
java
import com.bim.bimbookshop.util.JwtUtil;
import io.jsonwebtoken.Claims;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 登录拦截器
*/
@Component
public class LoginInterceptor implements HandlerInterceptor {
/**
* 过滤除登录请求外的其他请求
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if ("token".equals(cookie.getName())) {
String userToken = cookie.getValue();
if (!StringUtils.hasText(userToken)) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED); // 未认证
}
// 解析token并验证
try {
Claims claims = JwtUtil.parseJWT(userToken);
claims.getSubject(); // 如果解析成功,代表用户已登录
} catch (Exception e) {
System.out.println("Token信息出错");
return false; // 如果token无效,返回false,阻止访问
}
return true; // 放行
}
}
}
return false; // 如果没有找到token,则返回false,拒绝访问
}
}
3. 创建JWT工具类
我们需要一个工具类来生成和解析JWT。这个类会提供生成JWT的功能,并在拦截器中进行解析和验证。
创建JwtUtil类:
java
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;
/**
* JWT工具类
*/
public class JwtUtil {
// 设置过期时间,单位为毫秒
public static final Long JWT_TTL = 60 * 60 * 1000L; // 1小时
public static final String JWT_KEY = "qcby"; // 密钥
/**
* 创建token
* @param subject 主题,可以是用户的ID或其他信息
* @return JWT token
*/
public static String createJWT(String subject) {
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
long expMillis = nowMillis + JWT_TTL;
Date expDate = new Date(expMillis);
SecretKey secretKey = generalKey();
JwtBuilder builder = Jwts.builder()
.setId(UUID.randomUUID().toString()) // 唯一的ID
.setSubject(subject) // 主题
.setIssuer("wd") // 签发者
.setIssuedAt(now) // 签发时间
.signWith(signatureAlgorithm, secretKey) // 使用HS256算法进行加密
.setExpiration(expDate); // 设置过期时间
return builder.compact();
}
/**
* 生成加密后的秘钥
* @return SecretKey
*/
public static SecretKey generalKey() {
byte[] encodedKey = Base64.getDecoder().decode(JWT_KEY);
return new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
}
/**
* 解析JWT
* @param jwt token
* @return Claims
* @throws Exception
*/
public static Claims parseJWT(String jwt) throws Exception {
SecretKey secretKey = generalKey();
return Jwts.parser()
.setSigningKey(secretKey)
.parseClaimsJws(jwt)
.getBody();
}
}
4. 在登录时创建JWT并存入Cookie
在用户登录成功后,我们会生成一个JWT,并将其保存到浏览器的Cookie中。这样,用户下次访问时,可以通过解析Cookie中的token来验证登录状态。
登录方法:
java
public ResponseResult Login(Login login, HttpServletResponse response) {
// 登录验证逻辑
// 登录成功后,根据用户ID生成JWT
String token = this.jwtUtil.createJWT(String.valueOf(user.getUserId()));
// 将token存入Cookie中
Cookie cookie = new Cookie("token", token);
cookie.setPath("/"); // 将cookie作用域设置为整个网站
cookie.setMaxAge(36000); // 设置cookie过期时间为10小时
response.addCookie(cookie); // 将cookie添加到响应中
return new ResponseResult("登录成功");
}
二、配置JWT依赖和环境
1. 添加JWT依赖
为了能够使用JWT库,我们需要在pom.xml
中添加依赖。
java
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
2. 配置JWT环境
我们可以在application.yml
或application.properties
中配置JWT相关的参数,例如过期时间、密钥等。
java
spring:
...
jwt:
secret: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4K67DMlSPXbgG0MPp0gH
expire: 86400000 # 设置过期时间为一天(单位为毫秒)
subject: door # 设置令牌的主题
总结
通过以上步骤,我们在Spring Boot应用中实现了基于JWT的登录认证功能。我们使用拦截器对用户请求进行拦截,只有拥有有效JWT的用户才能访问受保护的资源。这样可以有效地保证系统的安全性和用户体验。