云计算百科
云计算领域专业知识百科平台

实现登录拦截功能

一、前言:为什么需要登录拦截?

在一个典型的 Web 应用中,我们经常遇到这样的需求:

  • 用户未登录时,访问 /user/profile 应自动跳转到登录页
  • 管理员才能访问 /admin/* 路径
  • 某些接口只允许已认证用户调用(如修改密码、下单)

如果每个 Controller 都手动写 if (session == null),不仅重复、易漏,还难以维护。

解决方案:使用 Spring MVC 拦截器(Interceptor)统一处理!

本文将带你: ✅ 手动实现登录状态拦截 ✅ 精准配置拦截路径与放行规则 ✅ 支持 JSON 接口返回 401(前后端分离场景) ✅ 避开常见陷阱(如静态资源被拦截)


二、核心原理:拦截器 vs 过滤器

特性拦截器(Interceptor)过滤器(Filter)
所属框架 Spring MVC Servlet 容器
能否注入 Bean ✅ 可以 ❌ 不行(除非特殊配置)
执行时机 Controller 方法调用前后 请求进入容器时
是否支持路径匹配 ✅ 精确(AntPathMatcher) ❌ 需手动解析 URL
适用场景 业务级拦截(如登录、权限) 编码、日志、安全头等底层处理

📌 结论:登录拦截优先使用 Interceptor!


三、实战:基于 Session 的登录拦截器

1. 前提:已有登录逻辑(存 Session)

假设用户登录成功后,已将用户名存入 Session:

// 登录成功时
session.setAttribute("currentUser", "zhangsan");


2. 自定义拦截器

@Component
public class LoginInterceptor implements HandlerInterceptor {

@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {

// 1. 获取当前会话
HttpSession session = request.getSession(false);

// 2. 判断是否已登录
if (session == null || session.getAttribute("currentUser") == null) {

// 3. 判断是页面请求还是 AJAX 请求
String contentType = request.getHeader("Content-Type");
String accept = request.getHeader("Accept");

boolean isAjax = (contentType != null && contentType.contains("application/json")) ||
(accept != null && accept.contains("application/json"));

if (isAjax) {
// 前后端分离:返回 JSON 错误
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("{\\"code\\":401,\\"msg\\":\\"请先登录\\"}");
return false;
} else {
// 传统 Web:重定向到登录页
response.sendRedirect("/login");
return false;
}
}

// 已登录,放行
return true;
}
}

✅ 智能判断:自动区分页面跳转和 API 调用,返回不同响应!


3. 注册拦截器并配置路径

@Configuration
public class WebConfig implements WebMvcConfigurer {

@Autowired
private LoginInterceptor loginInterceptor;

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor)
// 拦截哪些路径
.addPathPatterns("/user/**", "/order/**", "/profile/**")
// 放行哪些路径(必须放行登录、静态资源等)
.excludePathPatterns(
"/login",
"/doLogin",
"/logout",
"/css/**",
"/js/**",
"/images/**",
"/captcha", // 图形验证码
"/error", // 错误页
"/webjars/**" // Bootstrap 等
);
}
}

🔑 关键点:

  • addPathPatterns:指定需要保护的路径
  • excludePathPatterns:必须放行登录相关和静态资源,否则页面样式丢失!

四、进阶:支持角色权限拦截(可选)

如果需要区分普通用户和管理员:

// 登录时存入角色
session.setAttribute("role", "admin");

// 拦截器中增强判断
String role = (String) session.getAttribute("role");
if (!"admin".equals(role)) {
response.sendError(403, "无权访问");
return false;
}

或定义多个拦截器:

  • LoginInterceptor:只校验是否登录
  • AdminInterceptor:校验是否为管理员(应用于 /admin/**)

五、前后端分离场景:纯 API 拦截

如果你的项目是 Vue/React + Spring Boot,所有接口都返回 JSON,可简化拦截器:

@Component
public class ApiLoginInterceptor implements HandlerInterceptor {

@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {

HttpSession session = request.getSession(false);
if (session == null || session.getAttribute("currentUser") == null) {
response.setStatus(401);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("{\\"error\\":\\"Unauthorized\\",\\"message\\":\\"请先登录\\"}");
return false;
}
return true;
}
}

// 配置:拦截所有 /api/** 开头的请求
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new ApiLoginInterceptor())
.addPathPatterns("/api/**")
.excludePathPatterns("/api/auth/login", "/api/public/**");
}

💡 前端收到 401 后,跳转到登录页即可。


六、避坑指南:常见问题与解决方案

❌ 坑 1:静态资源(CSS/JS)被拦截,页面样式错乱

原因:未在 excludePathPatterns 中放行 /css/** 等路径 解决:务必放行所有静态资源目录

❌ 坑 2:登录成功后仍被拦截

原因:Session 未正确创建,或拦截器执行顺序问题 排查:

  • 检查 session.setAttribute() 是否执行
  • 确保登录接口在 excludePathPatterns 中

❌ 坑 3:拦截器中无法注入其他 Service

原因:拦截器未被 Spring 管理 解决:加上 @Component 注解,并通过 @Autowired 注入

❌ 坑 4:跨域请求导致 Cookie 丢失(前后端分离)

现象:前端携带 withCredentials: true,但后端收不到 JSESSIONID 解决:配置 CORS 允许凭证

@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("http://localhost:8080");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}


七、替代方案对比

方案优点缺点适用场景
自定义 Interceptor 简单、灵活、可控 需手动维护 中小型项目
Spring Security 功能强大、企业级 学习成本高 大型系统、高安全要求
AOP 切面 可按注解拦截 无法处理 URL 路径 特定方法级控制

📌 建议:

  • 快速上线 → Interceptor
  • 金融/政务系统 → Spring Security

八、结语

感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!

赞(0)
未经允许不得转载:网硕互联帮助中心 » 实现登录拦截功能
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!