预检响应在角度中没有 HTTP 正常状态

问题描述 投票:0回答:7

我的服务中定义了以下获取请求:

createAuthorizationHeader(user, pass) {
  let headers: HttpHeaders = new HttpHeaders;
  headers = headers.append('Accept', 'application/json, text/plain, */*');
  headers = headers.append('Authorization', 'Basic ' + btoa(user + ':' + pass));
  headers = headers.append('Content-Type', 'application/json; charset=utf-8');
    console.log(headers);
    return this.http.get(this._loginUrl, {
      headers: headers
    });
}

结果是:

OPTIONS https://localhost:8443/delivery/all 401 ()

Failed to load https://localhost:8443/delivery/all: Response for preflight does not have HTTP ok status.

HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: null, ok: false, …}

我也使用 Postman 发出了相同的 post 请求,但一切正常,因此本地服务器可以正常工作。

我不知道我的请求做错了什么。

angular http cors
7个回答
87
投票

CORS 合约要求飞行前的 OPTIONS 请求不需要进行身份验证。看起来您的后端需要对 OPTIONS 请求和 GET 进行身份验证。

当您使用 Postman 访问后端时,您仅发送 GET。 浏览器将首先发送一个 OPTIONS 请求(没有您的身份验证标头),并查找响应是否具有与发出请求的页面的来源相匹配的“Access-Control-Allow-Origin”标头。

如果对 OPTIONS 请求的响应不是 2xx,或者标头不存在,或者标头值与请求页面的来源不匹配,您将收到所遇到的错误,并且不会发出 GET 请求.

TLDR;将您的后端更改为在处理登录网址时不需要对 OPTIONS 方法进行身份验证。


12
投票

如果是 .Net Web API 项目,请编辑 web.config 并删除下面的标签。

<handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>

8
投票

默认情况下,浏览器不允许用户进行跨域请求。

从 Angular 来看,为了避免这个错误,我们可以使用代理配置。

假设 Angular ui 正在 localhost:4200 上工作,并且它想要调用其余端点 url,例如: https://localhost:8443/delivery/all

以下步骤将解决此问题。

  1. 在 Angular 应用程序根文件夹中创建 proxy.config.json 文件。 (package.json 文件存在的地方) 代理的作用是简单地在前端应用程序运行的同一域+端口处获取浏览器请求,然后将该请求转发到后端 API 服务器。 CORS 是一个浏览器安全问题,不适用于进行“后端到后端”通信(如中间有代理的情况)。

    内容应如下所示。

    样品:

    {
        "/delivery/all/*": {
        "target": "https://localhost:8443",
        "secure": false,
        "logLevel": "debug",
        "changeOrigin": true
        }
    }
    

    我们的应用程序内向 /delivery/all/... 发出的所有请求都将转发到 https://localhost:8443/delivery/all/

    注意:changeOrigin 属性。当您在后端使用某些虚拟代理(例如配置了 Apache2)时,您肯定必须将其设置为 true

  2. 在运行应用程序时添加代理配置。 Angular 支持“--proxy-config”,您可以在其中提供代理配置文件。 如果您使用“npm start”选项进行测试,则必须添加“--proxy-config”选项,如下所示。必须将其添加到 package.json 文件中。

     "scripts": {
    
    "ng": "ng",
    "start": "ng serve --proxy-config proxy.config.json",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
    }
    

    如果您直接使用“ngserve”运行,那么它已按如下所示进行修改。 “ng服务--proxy-config proxy.config.json”

  3. 我们的 Angular 应用程序中的 HTTP 调用可以更改为这样。服务器会自动将请求转发到“https://localhost:8443/delivery/all”。

    this.http.get('https://localhost:8443/delivery/all') .map(res => res.json());

    this.http.get('/delivery/all') .map(res => res.json());

这里是更多信息的链接:https://sudhasoftjava.wordpress.com/2018/10/05/proxy-configuration-in-angular/


5
投票

我们所做的是为 Cors 添加自定义配置。然后通过java服务器中的安全配置来启用它。如答案中所述,此服务器仅针对直接 REST 调用启用。

@Configuration
public class CorsConfig {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE").allowedOrigins("*")
                        .allowedHeaders("*");
            }
        };
    }
}

这涉及网络安全配置:

@Override
    protected void configure(final HttpSecurity http) throws Exception {
        http.csrf().disable()
                .antMatcher("/**")
                .authorizeRequests().and()
                .httpBasic()
                .and()
                .authorizeRequests().anyRequest().authenticated().and().cors();
    }

1
投票

在 POST 请求发送 OPTIONS 请求之前反应应用程序以检查您的 API。
您需要添加

nginx.conf
这个块。

location /api/ {
    if ($request_method = 'OPTIONS') {
        return 204;
    }
    proxy_pass http://localhost:8080;
}

0
投票

将此行添加到服务器标头配置的末尾

status_header(200);

应该可以解决问题


0
投票

库里好像有bug,我发了204(也可以,但只有200才算可以)

© www.soinside.com 2019 - 2024. All rights reserved.