【问题标题】:Angular HttpClient doesn't send POST, it sends OPTIONSAngular HttpClient 不发送 POST,它发送 OPTIONS
【发布时间】:2018-08-07 06:05:15
【问题描述】:

我是使用 Angular HttpClient 的新手(也会写英文)

我有一个问题,我正在尝试使用 POST 方法发送 HTTP 请求以协商 OAuth 令牌获取,但 Angular 发送 OPTIONS 请求:

服务:

login(username: string, password: string) {
const body = `username=${encodeURIComponent(username)}&password=${encodeURIComponent(password)}&grant_type=password`;

const httpOptions = {
  headers: new HttpHeaders({
    'Content-Type': 'application/x-www-form-urlencoded',
    'Authorization': 'Basic ' + btoa(TOKEN_AUTH_USERNAME + ':' + TOKEN_AUTH_PASSWORD)
  })
};  


return this.http.post<string>(AuthenticationService.AUTH_TOKEN, body, httpOptions);

结果:

对于我的后端,我使用的是 Spring Security,并添加了一个过滤器以允许 CORS:

@Bean
public FilterRegistrationBean corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");
    source.registerCorsConfiguration("/**", config);
    FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
    bean.setOrder(0);
    return bean;
}

【问题讨论】:

  • 您的身份验证服务器似乎与您的前端应用程序不在同一个域中,并且您面临 CORS(跨域资源共享)问题。
  • 您不能使用 XHR 调用 /token 端点。它应该从后端或本机应用程序访问。
  • 你是否也会从 spring 提供你的 Angular 应用程序,或者用户是否会从其他域下载脚本?

标签: angular spring-security oauth-2.0 angular5 spring-security-oauth2


【解决方案1】:

这与角度无关,这是您的浏览器在做的事情。

Check this issue.

我假设您的服务器在 localhost:8080 上运行,而您的 Angular 应用程序在 localhost:4200 上运行。由于您的请求是跨源请求,因此浏览器首先发送OPTIONS 请求以查看它是否安全。此时,您的服务器会返回一个带有 http 代码 401 的响应,这会阻止发出 post 请求。 要么你必须在你的服务器上做一些配置,要么你可以使用 webpack 代理。这仅适用于您的本地计算机。如果您从服务器提供捆绑的 Angular 应用程序,那么您无需为生产做任何事情。我使用这种技术已经有一段时间了,而且效果很好。

例子,

用户从 mydomain.com/ng-app 访问我的 Angular 应用程序 我还从同一个域 mydomain.com/api 提供我的 rest api

所以我的应用程序总是向它所提供服务的服务器发出请求,这在生产中不会出现问题。

对于后者,您可以执行以下操作

在项目的根目录下创建一个proxy.conf.json(在package.json 旁边) 并将以下内容放入

{
    "/api/": {
        "target": "http://localhost:8080",
        "secure": false,
        "changeOrigin": true
    }
}

在 package.json 中,编辑您的 start 脚​​本并使其成为 ng serve --proxy-config proxy.conf.json

另外,从您的前端,不要直接将请求发送到 localhost:8080,而只需编写类似 http.post('/api/getSomeData') 的内容,它将向 localhost:4200 发出请求,并将其重定向到 localhost:8080。这样,您就不必处理 CORS。

【讨论】:

  • 如果他将其部署在生产环境中或像 apache 或 nginx 这样的服务器上,这将无法正常工作
  • 如果他从同一个域提供 Angular 应用程序,它会工作得很好。
  • 假设他使用 webpack,它会工作,但如果他使用 webpack 以外的其他方式部署它,那么问题来了
  • 这与 webpack 无关。当您在不提及域的情况下发出请求时,它将向为前端应用程序提供服务的域发出请求。我一直在对我的项目做同样的事情,而且效果很好
  • 请查看link,因为您运行ng serve &lt;blah&gt;,它使用webpack 运行开发服务器来为您的角度应用程序提供服务。同样,如果 OP 在生产环境中使用 apache/nginx,则不会这样做。
【解决方案2】:

OPTIONS 请求首先发送是因为CORS,Angular 需要您的后端许可才能知道它是否可以POST。因此,在您的后端,您需要启用 CORS 才能发送 http 请求。

【讨论】:

    【解决方案3】:

    对于 Spring Boot 应用程序,要启用 cors 请求,请在您各自的控制器上使用 @CrossOrigin(origins = "*", maxAge = 3600)。

    Refer this

    【讨论】:

      【解决方案4】:

      【讨论】:

        【解决方案5】:

        使用 NestJS/Express 后端,我通过启用 CORS 解决了这个问题:https://docs.nestjs.com/techniques/security#cors

        【讨论】:

          【解决方案6】:

          最后我发现了错误。 过滤器的顺序不正确。我将它调整为 Ordered.HIGHEST_PRECEDENCE 这样它会覆盖 Spring 过滤器。

          @Bean
          public FilterRegistrationBean corsFilter() {
              UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
              CorsConfiguration config = new CorsConfiguration();
              config.setAllowCredentials(true);
              config.addAllowedOrigin("*");
              config.addAllowedHeader("*");
              config.addAllowedMethod("*");
              source.registerCorsConfiguration("/**", config);
              FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
              bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
              return bean;
          }
          

          【讨论】:

          • 请注意,您允许使用 CORS,这可能会导致安全漏洞。
          • 当然,这个bean只适用于开发环境
          • 检查我的答案,即使在开发环境中你也不需要这个 bean。
          • 使用您的代理,Angular 发出了一个 prefligth 请求,而我的后端阻止了它。它的答案对我不起作用。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-07-27
          • 1970-01-01
          • 1970-01-01
          • 2016-06-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多