嵌入Spring Boot项目的React路由无法正常工作问题排查
问题分析与解决方案
核心问题
- SPA路由未被Spring Boot转发:React作为单页应用,所有前端路由(如
/login、/dashboard)需要Spring Boot转发到index.html,否则Spring会将这些路径视为后端API请求,返回404。 - Spring Security配置不匹配SPA场景:
loginPage("/login")指向的后端端点不存在,导致404;同时明文密码未加密,不符合Spring Security的密码校验规则。 - 登录表单提交逻辑缺失:React登录页未正确向Spring Security的认证接口提交请求,导致登录流程无法触发。
解决方案步骤
1. 配置Spring Boot转发SPA路由
添加控制器,将所有前端路由请求转发到index.html,确保React路由能正常接管页面渲染:
@Controller public class SpaForwardController { // 覆盖所有需要React路由处理的路径 @GetMapping(value = {"/login", "/dashboard", "/logout"}) public String forwardToIndex() { return "forward:/index.html"; } }
或者通过WebMvcConfigurer配置全局转发规则,更通用:
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/login").setViewName("forward:/index.html"); registry.addViewController("/dashboard").setViewName("forward:/index.html"); registry.addViewController("/logout").setViewName("forward:/index.html"); } }
2. 修正Spring Security配置
- 调整登录页路径,确保Spring Security允许访问前端路由;
- 添加密码编码器,解决明文密码不被允许的问题;
- 修正退出跳转路径,避免logout后出现404;
- 放行静态资源(React打包后的css、js等)。
修改后的安全配置:
@Configuration @EnableWebSecurity public class DefaultWebSecurityConfig extends WebSecurityConfigurerAdapter { // 声明密码编码器Bean @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() // 放行静态资源和登录页 .antMatchers("/", "/login", "/static/**", "/css/**", "/js/**").permitAll() // 仅dashboard需要认证 .antMatchers("/dashboard").authenticated() .anyRequest().permitAll() .and() .formLogin() // 前端登录页路径(已被转发到index.html) .loginPage("/login") // Spring Security默认的认证处理端点,前端表单需提交到这里 .loginProcessingUrl("/login") .defaultSuccessUrl("/dashboard") .permitAll() .and() .logout() // 退出后跳转回登录页 .logoutSuccessUrl("/login") .permitAll(); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { // 使用加密后的密码(原密码为"user") auth.inMemoryAuthentication() .withUser("user") .password(passwordEncoder().encode("user")) .roles("employee"); } }
3. 调整React登录表单提交逻辑
确保登录表单以POST方法提交到/login,参数名使用Spring Security默认的username和password:
// Login组件示例 function Login() { const handleSubmit = (e) => { e.preventDefault(); const formData = new FormData(e.target); fetch('/login', { method: 'POST', body: new URLSearchParams(formData), headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).then(response => { if (response.ok) { window.location.href = '/dashboard'; } else { alert('登录失败,用户名或密码错误'); } }); }; return ( <div className="login-container"> <form onSubmit={handleSubmit}> <div> <label>用户名:</label> <input type="text" name="username" required /> </div> <div> <label>密码:</label> <input type="password" name="password" required /> </div> <button type="submit">登录</button> </form> </div> ); }
4. 确认maven-frontend插件打包配置
确保插件将React打包后的build目录内容复制到Spring Boot的静态资源目录(src/main/resources/static),示例pom.xml配置:
<plugin> <groupId>com.github.eirslett</groupId> <artifactId>frontend-maven-plugin</artifactId> <version>1.12.0</version> <executions> <execution> <id>install node and npm</id> <goals><goal>install-node-and-npm</goal></goals> <configuration> <nodeVersion>v16.18.0</nodeVersion> <npmVersion>8.19.2</npmVersion> </configuration> </execution> <execution> <id>npm install</id> <goals><goal>npm</goal></goals> <configuration><arguments>install</arguments></configuration> </execution> <execution> <id>npm run build</id> <goals><goal>npm</goal></goals> <configuration><arguments>run build</arguments></configuration> </execution> <execution> <id>copy built resources</id> <goals><goal>copy</goal></goals> <configuration> <from>target/reactapp/build</from> <to>src/main/resources/static</to> </configuration> </execution> </executions> </plugin>
验证步骤
- 执行
mvn clean package打包应用; - 启动Spring Boot应用,访问
http://localhost:8090/login,确认React登录页正常显示; - 输入
user/user登录,确认跳转到/dashboard; - 执行退出操作,确认返回登录页。
内容的提问来源于stack exchange,提问作者user2810351
相关产品推荐
相关产品推荐

