0

在开发模式下运行时,Spring Security发生配置问题,导致React前端(使用React路由器运行)上的登录页面重新定向。我相信重定向不会被我的前端所接受,这是因为我没有理解服务器端路由如何与SPA路由交互。Spring Security登录页面与SPA中的React Router重定向

我的开发前端Web服务器(使用Facebook创建React应用程序)在localhost:3000上运行,我的后端Spring Boot Tomcat在localhost:8080上运行。我已经启用了Spring Security,它可以在Tomcat服务器(端口8080)上正常工作;访问本地主机:8080转发到本地主机:8080 /登录。在访问localhost:3000时,我得到了一个交叉错误,因此在here中增加了对Spring的CORS支持。我也咨询了this Spring博文。它似乎工作,因为我不再得到交叉原点错误。然而,虽然没有登陆,从本地主机请求:3000为localhost:8080 /登录返回如下:

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> 
... 

这是我的前端Web服务器中的index.html主持。这很好,但我需要它转发到本地主机:3000 /登录,这将呈现登录页面index.html。

我相信它不会转发到/登录,因为路由设置的,它会从localhost:3000/ - >HttpSecurity.loginPage("/login")(春季) - >registry.addViewController("/login").setViewName("forward:/index.html")(春季) - ><Route path="/" component={ForwardToLandingPage} />(阵营路由器)

它出错的结束。我希望Tomcat服务器将前端重新指向:3000/login,但前端转到该组件。似乎服务器端重定向和前端React路由器之间存在问题。如果这太复杂了,我可能会把这整个Spring Security放到我的开发环境中。

这里是我的配置:

阵营路由配置

ReactDOM.render((
    <Router history={browserHistory}> 
     <Route path="/" component={ForwardToLandingPage} /> 
     <Route path="/login" component={Login} /> 
    </Router> 
    ), 
    document.getElementById('root') 
); 

Spring MVC的配置

@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"); 
    } 
} 

春CORS配置

@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; 
    } 
} 

春季安全配置

@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

你可以发布一个链接到Facebook创建React应用程序,它是否发出ajax请求或常规http请求? –

+0

'localhost:8080/login'是登录页面吗? – chaoluo

+0

感谢您的问题。我今天一直在做更多的尝试,我现在认为这个问题更多的是在我的后端和前端之间进行路由和重定向。我用我的发现和配置更新了我的问题。另外我应该补充一点,我遇到的问题是当我在我的开发环境中。直接访问端口8080或托管的AWS Elastic Beanstalk时,所有服务(包括前端)内容均可正常工作。如果修复太复杂,我只会在开发环境中禁用登录。 – Jannik

回答

-1

我们正在使用Spring安全的旧版本,我不知道它是否支持CORS与否。我已经使用Spring Security进行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问题。

+1

谢谢你的克劳斯。 :)刚刚添加它,它工作正常,因为我的CORS过滤器。我以为CORS在某种程度上打破了登录页面的重定向。我现在已经确定问题是只有路由和重定向,CORS工作正常。 – Jannik

相关问题