【问题标题】:Response for preflight does not have HTTP ok status in angular预检响应在角度中没有 HTTP ok 状态
【发布时间】:2019-02-02 11:28:23
【问题描述】:

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

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 发出了同样的发帖请求,但一切正常,所以本地服务器正常工作。

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

【问题讨论】:

  • Nit: application/json 没有字符集参数

标签: angular http cors


【解决方案1】:

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

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

如果对 OPTIONS 请求的响应不是 2xx,或者标头不存在,或者标头值与请求页面的来源不匹配,您将收到您遇到的错误,而 GET 请求不会制作。

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

【讨论】:

  • 您是否有任何关于如何更新 IIS 以使 OPTIONS 方法不需要身份验证的其他信息?
  • @Daryl 我们在应用程序级别(而不是在 IIS 上)这样做。如果您需要有关如何完成此操作的更多详细信息,请告诉我
  • 所以解决方案是将后端更改为不需要对 OPTIONS 进行身份验证,但是没有关于如何做到这一点的详细信息?如果可能,请展开。
  • 那完全依赖于服务器端的服务器/开发环境。如果您对如何在特定的服务器端环境中执行此操作有疑问,请在此处提出另一个问题。
【解决方案2】:

如果是 .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>

【讨论】:

  • 这是为我做的!谢谢!
  • 我爱你。这是为我做的。
【解决方案3】:

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

为了避免这个错误从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"
    }
    

    如果您直接使用“ng serve”运行,那么它已被修改如下。 "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/

【讨论】:

    【解决方案4】:

    我们所做的是为 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();
        }
    

    【讨论】:

    • 只需将 cors() 添加到我现有的配置中即可解决问题。
    • 按预期工作。谢谢
    【解决方案5】:

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

    status_header(200);
    

    应该解决问题

    【讨论】:

      【解决方案6】:

      在 POST 请求发送 OPTIONS 请求以检查您的 API 之前反应应用。
      你需要添加nginx.conf这个块。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-02-04
        • 2019-04-03
        • 1970-01-01
        • 2019-02-10
        • 2019-03-15
        • 2019-02-27
        • 2017-07-02
        • 2020-05-30
        相关资源
        最近更新 更多