import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.stp.StpUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* SaToken拦截器
*
* 该类的作用是在请求处理前进行权限认证,以确保只有登录用户可以访问受保护的资源
* 它通过实现HandlerInterceptor接口,使用Spring框架提供的拦截器机制来实现功能
*
* href:https://sa-token.cc/doc.html#/
*
*/
@Component
public class SaTokenInterceptor implements HandlerInterceptor {
/**
* 一键控制权限认证开关
*/
@Value("${sa-token.is-auth}")
private boolean isAuth;
/**
* 在请求处理前进行权限认证
*
* 如果权限认证开关打开,该方法会检查用户是否已登录
*
* @param request 用于获取请求信息
* @param response 用于向客户端返回信息
* @param handler 当前处理请求的处理器
* @return 如果权限认证通过或未启用权限认证,返回true,继续执行后续的请求处理;否则返回false,中断请求处理
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (isAuth) {
try {
// 如果权限认证开启,校验登录状态
StpUtil.checkLogin();
} catch (NotLoginException e) {
// 捕获未登录或 Token 过期的异常,通知前端跳转
response.setContentType("application/json;charset=UTF-8");
// 这里设置4001 未授权
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().write("{\"code\":4001, \"message\":\"未登录或登录已过期\", \"redirect\":\"/auth/inner-login\"}");
return false;
}
}
return true;
}
}
saToken的pom依赖
<!-- Sa-Token权限认证,在线文档:https://sa-token.cc -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.39.0</version>
</dependency>
application-dev.yml的配置
# 权限认证框架
sa-token:
# 一键控制权限认证开关
is-auth: true
token-name: token
# Token 有效期(秒)
timeout: 2592000
# 是否允许同一账号多地同时登录
is-concurrent: true
# token风格
token-style: uuid
# 是否输出操作日志
is-log: true
# 不读取cookie,防止Cookie帮你自动提交Token
is-read-cookie: true
这段代码定义了一个 SaTokenInterceptor 类,它是一个 Spring MVC 的拦截器,用于处理权限认证。拦截器的功能是确保只有已登录的用户能够访问某些受保护的资源。下面是对代码的详细解释:
1.导入的依赖
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.stp.StpUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
2.SaTokenInterceptor 类的声明
@Component
public class SaTokenInterceptor implements HandlerInterceptor
3.成员变量:权限开关
@Value("${sa-token.is-auth}")
private boolean isAuth;
@Value("${sa-token.is-auth}"): 从 application.properties
或 application.yml
配置文件中读取 sa-token.is-auth
的值并赋给 isAuth
。该配置项控制是否启用权限认证。4.preHandle 方法:请求前权限认证
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (isAuth) {
try {
// 如果权限认证开启,校验登录状态
StpUtil.checkLogin();
} catch (NotLoginException e) {
// 捕获未登录或 Token 过期的异常,通知前端跳转
response.setContentType("application/json;charset=UTF-8");
// 这里设置4001 未授权
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().write("{\"code\":4001, \"message\":\"未登录或登录已过期\", \"redirect\":\"/auth/inner-login\"}");
return false;
}
}
return true;
}
preHandle
方法: 这是HandlerInterceptor
接口中的一个方法,它在请求处理之前被调用。它可以用来做权限认证、日志记录等操作。如果返回 true,请求会继续向下执行;如果返回 false,则请求会被中断。当然配置了权限肯定也要配置拦截器
import cn.ac.ict.knowledge.graph.common.interceptor.SaTokenInterceptor;
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 WebConfig implements WebMvcConfigurer {
/**
* 自动注入SaTokenInterceptor,用于拦截请求进行权限验证等操作
*/
@Autowired
private SaTokenInterceptor saTokenInterceptor;
/**
* 添加拦截器配置
* 此方法用于向Spring MVC框架注册拦截器,并指定拦截器的拦截路径
*
* @param registry 拦截器注册器,用于注册自定义拦截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 除登陆、注册接口,拦截所有接口
registry.addInterceptor(saTokenInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/auth/inner-login",
"/auth/inner-update",
"/menu/get",
"/swagger-ui.html",
"/v3/api-docs/**",
"/swagger-resources/**",
"/webjars/**",
"/doc.html",
"/v*/api-docs**");
}
}
其实上面应该也要根据是否开启权限判断,是否使用拦截器
if (isAuth) { // 根据配置判断是否启用拦截器
registry.addInterceptor(saTokenInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/auth/inner-login", "/auth/inner-update", "/menu/get",
"/swagger-ui.html", "/v3/api-docs/**", "/swagger-resources/**",
"/webjars/**", "/doc.html", "/v*/api-docs**");
}