Spring Web页面中自动注入登录响应Token并实现登录后重定向的问题
Spring Web页面中自动注入登录响应Token并实现登录后重定向的问题
嗨,我刚接触Spring Security的时候也遇到过类似的问题,咱们一步步来解决:
首先要明确两个核心需求:登录成功后重定向到首页,以及后续跳转页面时自动携带Token无需重复登录。下面是具体的实现方案:
一、修改登录/注册接口,实现重定向+Token存储
你之前的loginSuccess和registerSuccess方法返回的是DTO,没法直接重定向。我们可以把返回类型改成String,同时把登录生成的Token存入HttpOnly Cookie(浏览器会自动在后续请求中携带这个Cookie,无需前端手动处理,还能防止XSS攻击)。
修改登录接口代码
@PostMapping("/auth/loginSuccess") public String loginUser(ApplicationUser user, HttpServletResponse response) { // 调用认证服务获取Token LoginResponseDTO loginResponse = authenticationService.loginUser(user.getUsername(), user.getPassword()); // 创建Cookie存储JWT Token Cookie jwtCookie = new Cookie("JWT_TOKEN", loginResponse.getToken()); jwtCookie.setPath("/"); // 设置Cookie作用域为全站 jwtCookie.setMaxAge(3600); // 设置过期时间为1小时(单位:秒) jwtCookie.setHttpOnly(true); // 禁止前端JS读取,提升安全性 // 如果是HTTPS环境,还可以设置jwtCookie.setSecure(true); response.addCookie(jwtCookie); // 重定向到首页(这里假设你的首页映射是"/"或者"/index") return "redirect:/"; }
修改注册接口代码
如果希望注册后自动登录并跳转到首页,可以参考下面的写法:
@PostMapping("/auth/registerSuccess") public String registerUser(ApplicationUser user, HttpServletResponse response) { // 完成用户注册 ApplicationUser registeredUser = authenticationService.registerUser(user.getUsername(), user.getPassword()); // 注册成功后自动登录,获取Token LoginResponseDTO loginResponse = authenticationService.loginUser(registeredUser.getUsername(), user.getPassword()); // 同样将Token存入Cookie Cookie jwtCookie = new Cookie("JWT_TOKEN", loginResponse.getToken()); jwtCookie.setPath("/"); jwtCookie.setMaxAge(3600); jwtCookie.setHttpOnly(true); response.addCookie(jwtCookie); return "redirect:/"; }
二、配置Spring Security,自动从Cookie中提取Token验证
现在Token已经存在Cookie里了,我们需要让Spring Security在每次请求时自动从Cookie中读取Token并完成认证,这样后续跳转页面就不用重复登录了。
1. 编写自定义JWT过滤器
这个过滤器负责从Cookie中提取Token,验证有效性后将用户信息存入SecurityContext:
public class JwtAuthenticationFilter extends OncePerRequestFilter { private final JwtTokenProvider jwtTokenProvider; public JwtAuthenticationFilter(JwtTokenProvider jwtTokenProvider) { this.jwtTokenProvider = jwtTokenProvider; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // 从Cookie中获取Token String token = getTokenFromCookie(request); // 验证Token是否有效 if (token != null && jwtTokenProvider.validateToken(token)) { // 获取用户认证信息 Authentication authentication = jwtTokenProvider.getAuthentication(token); // 将认证信息存入SecurityContext,后续接口就能识别当前登录用户 SecurityContextHolder.getContext().setAuthentication(authentication); } filterChain.doFilter(request, response); } // 从请求Cookie中提取JWT Token private String getTokenFromCookie(HttpServletRequest request) { Cookie[] cookies = request.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { if ("JWT_TOKEN".equals(cookie.getName())) { return cookie.getValue(); } } } return null; } }
2. 配置Spring Security
在Security配置类中添加上面的过滤器,让它在默认的用户名密码过滤器之前执行:
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { private final JwtTokenProvider jwtTokenProvider; public SecurityConfig(JwtTokenProvider jwtTokenProvider) { this.jwtTokenProvider = jwtTokenProvider; } @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() // 如果是前后端分离或不需要CSRF保护可以关闭 .authorizeRequests() // 允许注册、登录相关接口匿名访问 .antMatchers("/auth/**").permitAll() // 其他所有接口需要认证才能访问 .anyRequest().authenticated() .and() // 添加自定义JWT过滤器,在默认的用户名密码过滤器之前执行 .addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider), UsernamePasswordAuthenticationFilter.class); } }
补充说明
- 这里的
JwtTokenProvider是你项目中负责生成、解析JWT的工具类,确保它能正确从Token中解析出用户的权限和身份信息。 - 如果你的项目不是用JWT,而是用Session认证,其实Spring Security默认就会用Session Cookie来管理登录状态,你只需要调整登录接口的重定向逻辑即可,不需要额外写JWT过滤器。
- 如果你需要前端手动操作Token(比如发起AJAX请求),可以把Token存入LocalStorage,但HttpOnly Cookie的安全性更高,优先推荐。
备注:内容来源于stack exchange,提问作者Jablko
相关产品推荐
相关产品推荐

