预检请求在Chrome,Safary,Opera上失败

时间:2017-04-03 08:06:29

标签: spring-security cors

我在Springsecurity backen项目+ Angulajs前端的CORS请求上苦苦挣扎。 CORS请求在IE上运行正常(也有curl,wget和python请求),但由于Preflight的错误请求,Chrome和Safary失败了。 我知道那些浏览器正在阻止CORS POST,一旦到达后端就使请求为空,事实上当我从后端注销请求时我看不到任何数据。我尝试了所有可能的组合:

前端方面:

1)$ http(方法:POST)

2)$ http.post(

3)添加标志:Access-Control-Allow-Origin,Access-Control-Expose等

4)添加所有可能的标题组合:'Content-Type':'application /

浏览器端:

1)使用标志启动chrome: - disable-web-security

2)安装Chrome扩展程序CORS

后端方:

1)Spring Security禁用csfr

2)Spring Security Permit all

3)Spring Security HttpMethod.OPTION

4)设置一个接受所有来源的CORS过滤器:“*”

5)用于弹簧扩展WebMvcConfigurerAdapter类的激活CORS框架。

没什么,NHOTING为我工作了!

我在另一篇文章中讨论了这个问题:CORS POST request fails on Chrome, Safari and Firefox 我仍然无法执行CORS请求,现在这是我的主要问题,我怀疑问题出在LoginFilter中:

    public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {

        private TokenAuthenticationService tokenAuthenticationService;

        public JWTLoginFilter(String url, AuthenticationManager 

authenticationManager) {
        super(new AntPathRequestMatcher(url));
        setAuthenticationManager(authenticationManager);
        tokenAuthenticationService = new TokenAuthenticationService();
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
            throws AuthenticationException, IOException, ServletException {

        try {
            ServletInputStream inputStream = httpServletRequest.getInputStream();
            httpServletRequest.getCharacterEncoding();
            AccountCredentials credentials = null;
            ObjectMapper mapper = new ObjectMapper();

            credentials = mapper.readValue(inputStream, AccountCredentials.class);
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(credentials.getUsername(), credentials.getPassword());
            return getAuthenticationManager().authenticate(token);
        } catch (JsonMappingException e) {
            e.printStackTrace();
            throw e;
        } catch (JsonParseException e) {
            e.printStackTrace();
            throw e;
        } catch (AuthenticationException e) {
            e.printStackTrace();
            throw e;
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication)
            throws IOException, ServletException {
        AccountCredentials cred = (AccountCredentials) authentication.getPrincipal();
        tokenAuthenticationService.addAuthentication(response, cred);
    }

}

修改 Google Chrome上的确切错误是:

:8000/#!/login:1 XMLHttpRequest cannot load http://localhost:8080/myApp/login. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access. The response had HTTP status code 403.

2 个答案:

答案 0 :(得分:0)

所以我发现它与请求标头没有任何关系,但问题是响应标头。

要使预检通过,必须映射所有响应标头,例如:

response.addHeader("Access-Control-Expose-Headers", "xsrf-token, Authorization, Barer, Token");

答案 1 :(得分:-1)

在发送实际请求之前,浏览器本身会使用动词选项自动发送预检请求。 您必须将服务器配置为在发送此预检请求时发送带有某些标头的响应。使用弹簧安全性,您可以使用:

@Provider
@Component
public class CrossDomainContainerResponseFilter implements ContainerResponseFilter {

    @Override
    public void filter(ContainerRequestContext containerRequestContext,
            ContainerResponseContext containerResponseContext) throws IOException {

        containerResponseContext.getHeaders().add("Access-Control-Allow-Origin", "YOUR FRONTEND URI");

        containerResponseContext.getHeaders().add("Access-Control-Allow-Headers",
                    "Access-Control-Allow-Origin");
        containerResponseContext.getHeaders().add("Access-Control-Allow-Credentials", "true");
        containerResponseContext.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
    }
}

如果您使用的是XML配置,还可以使用<cors />标记。

--disable-web-security在Chrome上从未对我有用。但它适用于Vivaldi浏览器。