Spring Boot MVC应用集成JWT令牌实现登录认证求助
解决Spring Boot MVC自定义登录页返回JWT的问题
核心思路
MVC场景下的表单登录默认是登录成功后跳转页面,要返回JWT需自定义登录成功处理器,在用户认证通过后生成令牌,再根据业务需求选择传递方式:优先用Cookie存储(安全),也可返回JSON或通过URL参数传递(不推荐)。
1. 自定义登录成功处理器
创建CustomAuthenticationSuccessHandler类,实现AuthenticationSuccessHandler接口,在认证成功后生成JWT并处理传递逻辑:
import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.savedrequest.SavedRequest; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler { private final JwtTokenUtil jwtTokenUtil; public CustomAuthenticationSuccessHandler(JwtTokenUtil jwtTokenUtil) { this.jwtTokenUtil = jwtTokenUtil; } @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { // 获取登录用户信息,生成JWT UserDetails userDetails = (UserDetails) authentication.getPrincipal(); String jwtToken = jwtTokenUtil.generateToken(userDetails); // 方案1:将JWT存入HttpOnly Cookie(推荐,防XSS) Cookie jwtCookie = new Cookie("JWT_TOKEN", jwtToken); jwtCookie.setHttpOnly(true); jwtCookie.setSecure(true); // 生产环境开启,仅HTTPS传输 jwtCookie.setPath("/"); jwtCookie.setMaxAge(24 * 60 * 60); // 有效期1天 response.addCookie(jwtCookie); // 跳转到登录前的目标页面或默认首页 String targetUrl = request.getSession().getAttribute("SPRING_SECURITY_SAVED_REQUEST") != null ? ((SavedRequest) request.getSession().getAttribute("SPRING_SECURITY_SAVED_REQUEST")).getRedirectUrl() : "/dashboard"; response.sendRedirect(targetUrl); // ------------------------------ // 方案2:直接返回JSON令牌(适合前端需拿令牌发请求的场景) // response.setContentType("application/json"); // response.getWriter().write("{\"token\":\"" + jwtToken + "\"}"); // response.getWriter().flush(); } }
2. 配置Spring Security使用自定义处理器
在SecurityConfig中替换默认的登录成功处理器:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; @Configuration @EnableWebSecurity public class SecurityConfig { private final JwtTokenUtil jwtTokenUtil; public SecurityConfig(JwtTokenUtil jwtTokenUtil) { this.jwtTokenUtil = jwtTokenUtil; } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth .antMatchers("/login", "/css/**", "/js/**").permitAll() .antMatchers("/students/**").hasRole("ADMIN") .antMatchers("/subjects/**").hasRole("USER") .anyRequest().authenticated() ) .formLogin(form -> form .loginPage("/login") // 自定义登录页路径 .loginProcessingUrl("/do-login") // 表单提交接口 .successHandler(customAuthenticationSuccessHandler()) // 配置自定义处理器 .failureUrl("/login?error=true") .permitAll() ) .logout(logout -> logout .logoutSuccessUrl("/login?logout=true") .permitAll() ); // 若需用JWT保护接口,添加JWT过滤器 // http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); return http.build(); } @Bean public AuthenticationSuccessHandler customAuthenticationSuccessHandler() { return new CustomAuthenticationSuccessHandler(jwtTokenUtil); } }
3. 页面中获取JWT(针对Cookie方案)
前端页面可通过JS读取Cookie,后续AJAX请求时在请求头携带令牌:
// 从Cookie中提取JWT function getCookie(name) { let value = "; " + document.cookie; let parts = value.split("; " + name + "="); if (parts.length === 2) return parts.pop().split(";").shift(); } // 发起带令牌的请求 function fetchStudents() { const token = getCookie('JWT_TOKEN'); fetch('/students', { headers: { 'Authorization': 'Bearer ' + token } }) .then(response => response.json()) .then(data => console.log(data)); }
注意事项
- 确保
JwtTokenUtil能生成包含用户权限的令牌,后续JWT过滤器需解析权限做授权判断 - 生产环境必须开启Cookie的
Secure和HttpOnly属性,提升安全性 - 若用返回JSON的方案,需将登录表单改为AJAX提交,避免页面直接显示JSON内容
内容的提问来源于stack exchange,提问作者Anxheloo
相关产品推荐
相关产品推荐

