我遇到配置问题,当在开发模式下运行时,Spring Security会重定向到我的React前端的登录页面(与React Router一起运行)。我相信我的前端没有接收重定向,这是由于我对服务器端路由如何与SPA路由交互的理解。
我的开发前端Web服务器(使用Facebook Create React App)在localhost:3000上运行,我的后端Spring Boot Tomcat在localhost:8080上运行。我启用了Spring Security,它在Tomcat服务器上工作正常(端口8080);访问localhost:8080转发到localhost:8080 / login。访问localhost:3000时,我遇到了跨源错误,因此在Spring中添加了CORS支持,如here所述。我还咨询了this Spring博客文章。它似乎工作,因为我不再得到跨源错误。但是,在未登录的情况下,localhost:3000到localhost:8080 / login的请求将返回以下内容:
HTTP/1.1 200 OK
X-Powered-By: Express
Accept-Ranges: bytes
Access-Control-Allow-Origin: *
Content-Type: text/html; charset=UTF-8
Content-Length: 1496
ETag: W/"5d8-80rXYG+kNfQ/xEJ7J2f1PA"
Vary: Accept-Encoding
Date: Tue, 10 Jan 2017 12:04:07 GMT
Connection: keep-alive
<!DOCTYPE html>
...
这是我的前端网络服务器中托管的index.html。这很好,但我需要它转发到localhost:3000 / login,这会将登录页面呈现为index.html。
我认为由于路由设置而没有转发到/ login,它来自localhost:3000/
- &gt; HttpSecurity.loginPage("/login")
(春天) - &gt; registry.addViewController("/login").setViewName("forward:/index.html")
(春天) - &gt; <Route path="/" component={ForwardToLandingPage} />
(反应路由器)
最后出错了。我希望Tomcat服务器将前端重定向到:3000 / login,而前端则转到组件。似乎服务器端重定向和前端React Router到达正确位置之间存在问题。如果这太复杂而无法设置,我可能会在开发环境中删除整个Spring Security。
以下是我的配置:
反应路由配置
ReactDOM.render((
<Router history={browserHistory}>
<Route path="/" component={ForwardToLandingPage} />
<Route path="/login" component={Login} />
</Router>
),
document.getElementById('root')
);
Spring MVC config
@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// This forwarding is required, as my React app is rendering on a div
// element with the ID 'root' in /index.html. But is this part of the
// problem?
registry.addViewController("/").setViewName("forward:/index.html");
registry.addViewController("/login").setViewName("forward:/index.html");
}
}
Spring CORS config
@Configuration
public class MyConfiguration {
@Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("http://localhost:3000");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(0);
return bean;
}
}
Spring Security配置
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable() // temporary fix
.authorizeRequests()
.antMatchers("/h2-console", "/public/**", "/static/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
}
}
任何想法出了什么问题?
我想知道问题的解决方案是否应该涉及Tomcat,所以也检查了this。
感谢您的帮助! :)
答案 0 :(得分:-1)
我们使用的是较早版本的Spring安全版,但我不知道它是否支持CORS。我使用Spring安全性已有6年了,所以我刚刚创建了一个常规过滤器:
public class CORSFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest httpServletRequest = (HttpServletRequest) req;
// The headers needs to be on all responses.
String origin = httpServletRequest.getHeader("origin");
if (origin == null) {
// Make the developers life simpler. The browser adds the origin but it is a pain to
// for developers to add this header while testing.
origin = "*";
}
response.setHeader("Access-Control-Allow-Origin", origin.replace("\n", ""));
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Accept, Authorization");
// For options requests return immediately. Options does not require authentication so we want to return
// here to avoid all yet unknown security risks.
if (HttpMethod.OPTIONS.toString().equals(httpServletRequest.getMethod())) {
return;
}
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig) {
}
public void destroy() {
}
}
并在ChannelProcessingFilter之前添加,因此它成为过滤器链中的第一个过滤器。
http.addFilterBefore(new CORSFilter(), ChannelProcessingFilter.class);
http.formLogin().....
// all the other matchers and
如果这对您不起作用,那么我不确定它只是一个CORS问题。