Chrome,Safari和Firefox上的CORS POST请求失败 [英] CORS POST request fails on Chrome, Safari and Firefox

查看:325
本文介绍了Chrome,Safari和Firefox上的CORS POST请求失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个RESTfull后端,使用在localhost:8080上运行的Spring安全性实现,Login过滤器响应登录请求并在标头中放置一个令牌,我甚至没有实现Endpoint方法。 Spring Security通过下面这行代码:

  protected void configure(HttpSecurity http)throws Exception {
//禁用缓存
http.headers()。cacheControl();

http.csrf()。disable()//为我们的请求禁用csrf。
.authorizeRequests()
.antMatchers(/)。permitAll()
.antMatchers(/ login)。permitAll()
.anyRequest()。authenticated )
。和()
//我们过滤api / login请求
.addFilterBefore(new JWTLoginFilter(/ login,authenticationManager()),UsernamePasswordAuthenticationFilter.class)
...

前端是一个在localhost:8000上运行静态http服务器的Angularjs Nodejs NPM Bower项目。在前端,我做了一个简单的POST请求,如下所示:

  $ scope.login = function(){

var data = {
username:$ scope.username,
password:$ scope.password
}

$ http({
url:baseUrl,
method:POST,
data:data
})。then(function(response){
console.log(#### ## SUCCESS #####);
var headers = response.headers();
console.log(headers:+ JSON.stringify(headers));
var token = headers.authorization.split()[1];
console.log(token:+ token);
$ http.defaults.headers.common ['Authorization'] = token ;
$ location.path(/ view1);

},function(responseData){
//发生错误时异步调用
//或服务器返回带有错误状态的responseData
console.log(###### FAIL #####);
console.log(Respon se:+ JSON.stringify(responseData));
$ window.alert(登录失败);
});

这很像IE中的魅力(也包含curl,wget和python请求),但它很失败在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


$ b 后端:


$ b $ 1)Spring安全禁用csfr


$ b 2)Spring安全允许所有



3)Spring Security HttpMethod.OPTION

没有什么,NHOTING为我工作!



是否有我遗失的东西?



是否有另一种发送POST请求的方法?



编辑



如上所述,我修改了t他的课程如下:

WebSecurityConfig:

  .antMatchers( / login)。permitAll()
.anyRequest()。authenticated()
.and()
//我们过滤api / login请求
.addFilterBefore(new JWTLoginFilter (/ login,authenticationManager()),UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new CORSFilter(),BasicAuthenticationFilter.class)

,并将CORSFilter作为建议实现。



我也按照建议添加WebConfig类:

  @Configuration 
@EnableWebMvc
公共类WebConfig扩展WebMvcConfigurerAdapter {
$ b $ @覆盖
public void addCorsMappings (CorsRegistry注册表){
registry.addMapping(/ **).allowedOrigins(http:// localhost:8000)
.allowedMethods(PUT,POST);






$ b

由于空字符串,登录过滤器会抛出:
$ / p>

com.fasterxml.jackson.databind.JsonMappingException:由于输入结束而无法映射

这将会被春季安全会议拒绝访问。



我还试图将前端服务器移动到其他端口,然后是8000(4200,7000等)成功。

解决方案

您需要在春季启用Cors支持。在您的WebConfig中,您可以覆盖addCorsMappings

  @Configuration 
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

@Override
public void addCorsMappings(CorsRegistry registry){
registry.addMapping(/ **).allowedOrigins(http:// localhost:4200); //角度正在运行的网址。




$ b $ p $这使得cors可以用于整个应用程序。

  @Override 
public void addCorsMappings( CorsRegistry注册表){
registry.addMapping(/ api / **)
.allowedOrigins(http://domain2.com)
.allowedMethods(PUT,DELETE )
.allowedHeaders(header1,header2,header3);
}

您还可以在类和方法级别允许user @CrossOrgin

  @CrossOrigin(origin =http://domain2.com,
maxAge = 3600)
public class ApiController {

}

http://docs.spring.io/spring/docs/current/spring-framework- reference / html / cors.html



https://spring.io/guides/gs/rest-service-cors/


I have a RESTfull Backend implemented with Spring security running on localhost:8080, a Login filter responds to login requests with a token placed in the headers, I didn’t even implemented an Endpoint method for that, It is all done by Spring Security magic by the following line of code:

  protected void configure(HttpSecurity http) throws Exception {
        // disable caching
        http.headers().cacheControl();

        http.csrf().disable() // disable csrf for our requests.
            .authorizeRequests()
            .antMatchers("/").permitAll()
            .antMatchers("/login").permitAll()
            .anyRequest().authenticated()
            .and()
            // We filter the api/login requests
            .addFilterBefore(new JWTLoginFilter("/login", authenticationManager()), UsernamePasswordAuthenticationFilter.class)
    …

The frontend is a Angularjs Nodejs NPM Bower project running a static http server on localhost:8000. On frontend I make a simple POST request as follows:

   $scope.login = function () {

    var data = {
        "username":$scope.username,
        "password":$scope.password
    }

    $http({
        url: baseUrl,
        method: "POST",
        data: data
    }).then(function (response) {
        console.log("###### SUCCESS #####");
        var headers = response.headers();
        console.log("headers: "+JSON.stringify(headers));
        var token = headers.authorization.split(" ")[1];
        console.log("token: "+token);
        $http.defaults.headers.common['Authorization'] = token;
        $location.path("/view1");

    }, function (responseData) {
        // called asynchronously if an error occurs
        // or server returns responseData with an error status.
        console.log("###### FAIL #####");
        console.log("Response: "+JSON.stringify(responseData));
        $window.alert("Failed to Login");
    });

This works like a charm in IE (also with curl, wget and python requests) but it miserably failing on Chrome and Safary. I know that those Browsers are blocking CORS POSTs, making the request empty as soon as the reach the backend, in fact I don’t see any data when I log out the request from backend. I tried every possible combination of:

Frontend side:

1) $http(method: POST)

2) $http.post(

3) Adding flags: Access-Control-Allow-Origin, Access-Control-Expose, etc.

4) Adding all possible header combination: ‘Content–Type’:’application/

Browser side:

1) Start chrome with flag: --disable-web-security

2) Installing Chrome extension CORS

Backend side:

1) Spring Security Disable csfr

2) Spring Security Permit all

3) Spring Security HttpMethod.OPTION

Nothing, NHOTING worked for me!

is there something I’m missing?

Is there another way to send POST requests?

EDIT

As discussed, I modified the classes as follow:

WebSecurityConfig:

        .antMatchers("/login").permitAll()
        .anyRequest().authenticated()
        .and()
        // We filter the api/login requests
        .addFilterBefore(new JWTLoginFilter("/login", authenticationManager()), UsernamePasswordAuthenticationFilter.class)
        .addFilterBefore(new CORSFilter(), BasicAuthenticationFilter.class)

and implemented the CORSFilter as suggestet.

I also add the WebConfig class as suggested:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedOrigins("http://localhost:8000")
        .allowedMethods("PUT", "POST");
    }
}

Because of the empty string the login filter throws:

com.fasterxml.jackson.databind.JsonMappingException: No content to map due to end-of-input

this will be chatched by spring security which denied the access.

I also triyed to move the frontend server on other ports then 8000 (4200, 7000, etc.) with no success.

解决方案

You need to enable Cors support in spring. In your WebConfig you can override addCorsMappings

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedOrigins("http://localhost:4200");  //url of where angular is running.
    }
}

This enables cors for the whole application. You can also be more specific with your mappings allowing specific header, and methods.

@Override
public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/api/**")
            .allowedOrigins("http://domain2.com")
            .allowedMethods("PUT", "DELETE")
            .allowedHeaders("header1", "header2", "header3");
}

You can also allow user @CrossOrgin at the class and method level

@CrossOrigin(origin = "http://domain2.com",
             maxAge = 3600)
public class ApiController {

}

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cors.html

https://spring.io/guides/gs/rest-service-cors/

这篇关于Chrome,Safari和Firefox上的CORS POST请求失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆