在请求被处理前,执行一些公共逻辑,例如检查用户是否认证、是否有权限访问受保护的资源、日志记录等;
可以在请求被处理前,对请求的数据进行预处理,还可以对返回的结果进行统一处理。
1、Cors跨域处理#
在项目中创建config文件包,然后创建WebConfig类,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| package com.example.demo.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
/**
* 添加跨域资源共享(CORS)映射配置
* 该方法用于配置允许从哪些域对资源进行跨域请求
*
* @param registry CorsRegistry对象,用于注册CORS映射
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
// 配置跨域请求的映射路径,"/**"表示匹配所有路径
registry.addMapping("/**")
// 配置允许跨域请求的源,此处为本地开发环境地址
.allowedOrigins("http://localhost:5173")
// 允许在请求中携带凭证(如Cookies)
.allowCredentials(true)
// 配置允许的请求头,"*"表示允许所有请求头
.allowedHeaders("*")
// 配置允许的HTTP方法,此处允许GET、POST和DELETE请求
.allowedMethods("GET", "POST", "DELETE");
}
}
|
2、登录校验#
1、创建拦截器#
定义一个类并实现HandlerInterceptor接口。
可以根据需求实现接口中的三个方法:preHandle(在请求处理之前调用)、postHandle(在请求处理之后,但在视图渲染之前调用)和afterCompletion(在整个请求结束之后调用)
项目config文件下创建LoginInterceptor类,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
| package com.example.demo.config;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.StrUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {
/**
* 在请求处理之前进行预处理
*
* @param request HttpServletRequest对象,包含请求相关的信息
* @param response HttpServletResponse对象,用于响应请求
* @param handler 处理请求的处理器对象
* @return boolean 返回true表示继续执行下一个拦截器或处理器,返回false表示中断请求处理
* @throws Exception 如果预处理过程中发生异常,则抛出异常
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 获取请求的URI并记录,以便于后续的日志审计或调试
String requestURI = request.getRequestURI();
log.info("请求的URI:{}",requestURI);
// 获取请求头中的Authorization信息,用于验证用户身份
String authorization = request.getHeader("authorization");
log.info("请求的Authorization:{}",authorization);
// 如果Authorization信息不为空,进一步验证用户身份
if (authorization != null) {
// 使用sa-token工具类,通过Authorization信息获取用户ID
String userId = (String) StpUtil.getLoginIdByToken(authorization);
log.info("用户ID:{}",userId);
// 使用hutool工具类,验证用户ID是否为空,如果为空则抛出异常,表示用户未登录
if (StrUtil.isBlank(userId)){
throw new RuntimeException("用户未登录!");
}
// 将用户ID存入请求属性中,以便于后续的处理器可以使用
request.setAttribute("userId",userId);
} else {
// 如果Authorization信息为空,记录日志并返回false,中断请求处理
log.info("Token获取失败!");
return false;
}
// 返回true,表示预处理完成,继续执行下一个拦截器或处理器
return true;
}
}
|
2、将拦截器添加到配置文件中#
编辑config文件下的WebConfig类,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
| package com.example.demo.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private LoginInterceptor loginInterceptor;
/**
* 配置拦截器
*
* 该方法用于向应用程序添加拦截器,以在请求处理之前或之后执行特定逻辑
* 它特别指定了不需要拦截的路径,通常是登录和验证码相关的路径,以允许未登录的用户访问这些资源
*
* @param registry InterceptorRegistry的实例,用于注册拦截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 定义不需要拦截的路径列表,包括系统用户登录、普通用户登录和验证码相关路径
List<String> excludePathList = List.of(
"/system/user/login",
"/user/login",
"/captcha/**"
);
// 向registry中添加登录拦截器,应用于所有路径,但排除上述定义的路径
registry.addInterceptor(loginInterceptor)
.addPathPatterns("/**").excludePathPatterns(excludePathList);
}
}
|
3、权限校验#
1、创建拦截器#
项目config文件下创建PermissionInterceptor类,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| package com.example.demo.config;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
@Slf4j
@Component
public class PermissionInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 场景1:按角色校验:模拟从请求中获取用户角色
String userRole = (String) request.getSession().getAttribute("userRole");
// 模拟需要 ADMIN 角色才能访问的路径
if (request.getRequestURI().startsWith("/admin/")) {
if (!"ADMIN".equals(userRole)) {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "You don't have permission to access this resource.");
return false;
}
}
// 场景2:按接口权限校验:首次查询菜单权限时,将对应菜单关联的接口权限保存到redis中,后续直接从redis查询接口权限即可。
return true;
}
}
|
2、将拦截器添加到配置文件中#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| package com.example.demo.config;
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;
import java.util.List;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private PermissionInterceptor permissionInterceptor;
/**
* 配置拦截器
*
* 该方法用于向应用程序添加拦截器,以在请求处理之前或之后执行特定逻辑
*
* @param registry InterceptorRegistry的实例,用于注册拦截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 可以添加多个拦截器registry.addInterceptor(拦截器).addPathPatterns("/**");
// 向registry中添加权限拦截器,对所有路径进行拦截
registry.addInterceptor(permissionInterceptor).addPathPatterns("/**");
}
}
|