在开发模式下以Angular应用和Access-Control-Allow-Origin发送Cookie [英] sending cookies in Angular app and Access-Control-Allow-Origin in development mode

查看:116
本文介绍了在开发模式下以Angular应用和Access-Control-Allow-Origin发送Cookie的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个在 https://app.example.com:4202 上运行的Angular应用程序.我也有一个运行在 https://app2.example.com:4203 上的角度应用程序.它们都依赖于运行在 https://example.com 上的后端.

在每个后端php页面上,我都有一个测试,检查用户是否有权访问页面内容:

  if(!isset($ _ SESSION ["id"])){http_response_code(403);die(错误.未经授权的用户.");} 

现在,问题来了.为了使ajax请求发送cookie信息,我需要将 withCredentials 选项设置为 true

但是因为我的开发角度应用程序运行在4202上,并且Apache后端运行在443,所以我还需要在每个php文件中设置 header('Access-Control-Allow-Origin:*'); .那是您不允许做的事情.我收到一个Ajax错误:当请求的凭据模式为"include"时,响应中"Access-Control-Allow-Origin"标头的值不得为通配符"*".

我还尝试在我的Apache example.com 虚拟主机中设置此设置,并在php文件中删除了 header('Access-Control-Allow-Origin:*'); :

  SetEnvIf Origin ^(https?://.+ \ .example \ .com(?:: \ d {1,5})?)$ CORS_ALLOW_ORIGIN = $ 1标头附加访问控制允许来源%{CORS_ALLOW_ORIGIN} e env = CORS_ALLOW_ORIGIN标头合并Vary"Origin" 

但是在这种情况下,ajax请求抱怨有一个错误:

 响应中"Access-Control-Allow-Credentials"标头的值是",当请求的凭据模式为"include"时,该值必须为"true". 

所以我的问题是,如果您需要使用Cookie进行用户身份验证,并且只想拥有一个版本的应用程序(包括角度版本和后端版本),该怎么办?问题似乎是,角度应用程序在4202上运行,并且与后端(在443上运行)被认为具有不同的来源.请注意,此问题仅在开发期间发生,但是我真的很犹豫在本地安装1个版本机器和另一台在服务器上.

解决方案

除非您要专门构建一个 Access-Control-Allow-Origin ,否则您绝对不希望使用通配符.公共API.

您需要做的就是指定应该允许的确切地址.将其视为所有应允许访问的网站的后端服务器白名单.在您的情况下,这是两个Angular网站.

因此将标题更改为此:

  header('Access-Control-Allow-Origin:https://app.example.com:4202,https://app2.example.com:4203'); 

应该这样做.

在使用时,请将其添加到可重复使用的PHP包含中,因此无需在任何地方添加它.

修改

事实证明,您还需要第二个标头,以显式允许凭据.

  header('Access-Control-Allow-Credentials:true'); 

这是必需的,因为您要传递凭据.当服务和客户端不在同一服务器和主机上时,只要您想从浏览器调用Web服务,就需要使用我之前显示的 Access-Control-Allow-Origin 起源.>

I am writing an Angular app that runs on https://app.example.com:4202. I also have a running angular app that runs on https://app2.example.com:4203. Both of them are dependant on backend that runs at https://example.com.

On every backend php page, I have a test, that checks if user is authorized to access page contents:

if(!isset($_SESSION["id"])){
    http_response_code(403);
    die("Error. Unauthorized user.");  
}

Now, here comes the problem. In order for ajax requests to send cookie information I need to set withCredentials option to true

But because my development angular app runs on 4202 and by Apache backend at 443, I also need to set header('Access-Control-Allow-Origin: *'); in every php file. And thats something you are not allowed to do. I am getting an ajax error: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.

I also tried setting this in my apache example.com virtual host and deleted header('Access-Control-Allow-Origin: *'); in php file:

SetEnvIf Origin ^(https?://.+\.example\.com(?::\d{1,5})?)$   CORS_ALLOW_ORIGIN=$1
Header append Access-Control-Allow-Origin  %{CORS_ALLOW_ORIGIN}e   env=CORS_ALLOW_ORIGIN
Header merge  Vary "Origin"

but in this case, ajax request complains with an error:

The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'.

So my question is, what do you do, if you need user authentication using cookies and you want to have only 1 version of you application (both angular and backend)? The issue seems to be that angular app is running on 4202 and is considered to be of different origin as by backend, which runs on 443. Note that this problem only occurs during development, but I am really hesitant to have 1 version on my local machine and another on server.

解决方案

You absolutely don't want to use a wildcard for Access-Control-Allow-Origin, unless you're specifically building a public API.

All you need to do is specify the exact addresses that should be allowed. Think of it as the backend server's white-list for all websites that should be allowed access. In your case, those are the two Angular sites.

So change your header to this:

header('Access-Control-Allow-Origin: https://app.example.com:4202,https://app2.example.com:4203');

That should do it.

While you're at it, add this to a PHP include that you can reuse, so you don't need to add it everywhere.

Edit

It turns out you also need a second header, to explicitly allow credentials.

header('Access-Control-Allow-Credentials: true');

This is needed because you're passing credentials. The Access-Control-Allow-Origin origin I showed before is needed any time you want to call a web service from the browser when the service and client are not hosted on the same server and host.

这篇关于在开发模式下以Angular应用和Access-Control-Allow-Origin发送Cookie的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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