AngularJS 中的跨域 HTTP 请求失败

Posted

技术标签:

【中文标题】AngularJS 中的跨域 HTTP 请求失败【英文标题】:Cross Domain HTTP request fails in AngularJS 【发布时间】:2014-03-29 19:59:42 【问题描述】:

我有一个带有 Spring 的 REST 后端(在 Apache Tomcat 7 上启用了 CORS)和一个 AngularJS 客户端。两者都在不同的域上运行(就 CORS 而言)。

我正在尝试实现基本身份验证,但它仅在客户端和服务位于同一主机/端口号时才有效,即使在我验证 CORS 在服务器端工作正常之后也是如此。 (我通过禁用基本身份验证 impl 并简单地检查客户端是否能够从服务中提取数据来对其进行测试。只要服务上的 CORS 过滤器正常工作,它就可以正常工作 - 正如预期的那样)。

这是客户端配置

为 Angular 启用跨域请求(我听说 Angular 1.2+ 不需要它,但似乎两种方式都不起作用)

myApp.config(['$httpProvider', function ($httpProvider) 
    $httpProvider.defaults.useXDomain = true;
    delete $httpProvider.defaults.headers.common['X-Requested-With'];
 ]);

HTTP 调用

 $http(method: 'GET', url: url + userId, headers: 'Authorization': 'Basic ' + Base64.encode('admin' + ':' + 'password')).
    success(function(data, status, headers, config) 
//
    ).
    error(function(data, status, headers, config) 
//
    );

后端 CORS 过滤器

FilterRegistration corsFilter = container.addFilter("CORS", CORSFilter.class);
corsFilter.setInitParameter("cors.supportedMethods", "GET, HEAD, POST, PUT, DELETE, OPTIONS");
corsFilter.setInitParameter("cors.supportedHeaders", "Accept, Origin, X-Requested-With, Content-Type, Last-Modified");
corsFilter.setInitParameter("cors.supportsCredentials ", "false");
corsFilter.setInitParameter("cors.allowOrigin ", "*");
corsFilter.addMappingForUrlPatterns(null, false, "/*");

基本身份验证的 Spring Security

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter 

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception 
        auth
            .inMemoryAuthentication()
                .withUser("admin").password("password").roles("USER", "ADMIN");
    


     @Override
  protected void configure(HttpSecurity http) throws Exception 
    http.authorizeRequests()
        .antMatchers("/**").hasRole("USER")
        .anyRequest().anonymous()
        .and()
        .httpBasic();
      

我得到的错误(在另一个域上运行时客户端向服务发出的请求的整个错误)

Failed to load resource: the server responded with a status of 403 (Forbidden) (11:53:44:206 | error, network)
  at http://localhost:8081/myApp-service/user/6
Failed to load resource: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8383' is therefore not allowed access. (11:53:44:209 | error, network)
  at http://localhost:8081/myApp-service/user/6
XMLHttpRequest cannot load http://localhost:8081/myApp-service/user/6. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8383' is therefore not allowed access. (11:53:44:211 | error, javascript)
  at app/index.html

Chrome 请求标头

Request URL:http://localhost:8081/myApp-service/user/6
Request Method:OPTIONS
Status Code:403 Forbidden
Request Headersview source
Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:accept, authorization
Access-Control-Request-Method:GET
Connection:keep-alive
Host:localhost:8081
Origin:http://localhost:8383
Referer:http://localhost:8383/myApp-client/app/index.html
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36
Response Headersview source
Content-Length:93
Content-Type:text/plain;charset=ISO-8859-1
Date:Wed, 26 Feb 2014 18:55:00 GMT
Server:Apache-Coyote/1.1

如您所见,即使在编写了适当的配置之后,Angular 也无法处理 CORS 飞行前 OPTIONS。在同一个域中一切正常,后端的 CORS 过滤器经过测试可以独立工作。所以不确定我在这里缺少什么。谢谢!

【问题讨论】:

问题在于您的服务器代码,而不是 Angular。您可以通过查看您的服务器未正确处理 OPTIONS/preflight 的响应来了解。 @RayNicholus 这听起来很合理。到目前为止,我只怀疑过客户。由于我的 CORS 过滤器已经接受“OPTIONS”,我想不出我可以进行任何其他更改以使后端正常工作。有什么想法吗? 看起来您的服务器正在返回状态码 403。您可能想弄清楚它为什么会这样。 您需要查看您的服务器通过代理向 OPTIONS 发送的确切响应。 【参考方案1】:

我认为问题出在我的客户身上,但正如 Ray 指出的那样,问题出在我的服务上。

一旦我知道我需要调试我的服务,我就下载了 CORSFilter 的源代码,并适当地放置断点来研究服务器响应。

这样做后,我发现 CORS 过滤器在请求标头中遇到“授权”时会引发异常。这是因为我没有将它添加到支持的标头列表中。问题在我添加到列表后很快就解决了。

corsFilter.setInitParameter("cors.supportedHeaders", "Accept, Origin, X-Requested-With, Content-Type, Last-Modified, Authorization");

【讨论】:

你把这个和平的代码放在哪里?我的 spring security + angularjs 应用程序也有同样的问题... @NevyanovL mvnrepository.com/artifact/com.thetransactioncompany/…

以上是关于AngularJS 中的跨域 HTTP 请求失败的主要内容,如果未能解决你的问题,请参考以下文章

angularjs 1.2.6 的跨域请求错误

使用AngularJS返回xml的跨域ajax请求

使用 angularJS 的跨域请求

对 Python Bottle 的跨域 Angular JSONP 请求

AngularJS的$http的跨域问题

HTTP中的跨域请求HTTP报文结构状态码