Paw*_*Kam 5 nginx amazon-ec2 cors django-cors-headers
我使用 django-cors-headers 3.1.1 来处理 Django 后端和 Javascript 前端应用程序之间的请求和响应。传输是不安全的(即http,而不是https)。
\n\n当本地托管时,一切正常。但在服务器上部署后,我不再看到 CORS 标头。
\n\n\n\n错误信息:
\n\nAccess to XMLHttpRequest at \'http://[HOST_IP]/api/assets/\' from origin \'http://my_custom_domain.eu\' has been blocked by CORS policy: Response to preflight request doesn\'t pass access control check: No \'Access-Control-Allow-Origin\' header is present on the requested resource.\nRun Code Online (Sandbox Code Playgroud)\n\n我的 nginx 配置如下:
\n\nserver {\n listen 80;\n server_name [HOST_IP];\n\n location / {\n include proxy_params;\n proxy_pass http://unix:/home/ubuntu/[path_to_app]/app.sock;\n\n add_header \'Access-Control-Allow-Origin\' \'*\';\n add_header \'Access-Control-Allow-Methods\' \'GET, PUT, OPTIONS\';\n add_header \'Access-Control-Allow-Headers\' \'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range\';\n add_header \'Access-Control-Max-Age\' 86400;\n\n if ($request_method = \'OPTIONS\') {\n add_header \'Content-Type\' \'text/html; charset=utf-8\';\n add_header \'Content-Length\' 0;\n return 204;\n }\n if ($request_method = \'PUT\') {\n add_header \'Access-Control-Expose-Headers\' \'Content-Length,Content-Range\';\n }\n if ($request_method = \'GET\') {\n add_header \'Access-Control-Expose-Headers\' \'Content-Length,Content-Range\';\n }\n }\n\n location /static/ {\n autoindex on;\n alias /home/ubuntu/[path_to_app]/site/static/;\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\ndjango-cors-headers\xe2\x80\x99 设置现在在开发和生产中是相同的:
\n\nINSTALLED_APPS = (\n \xe2\x80\xa6\n "corsheaders",\n \xe2\x80\xa6\n)\nMIDDLEWARE = [\n \xe2\x80\xa6\n "corsheaders.middleware.CorsMiddleware",\n "django.middleware.common.CommonMiddleware",\n \xe2\x80\xa6\n]\nCORS_ORIGIN_ALLOW_ALL = True\nCORS_ALLOW_METHODS = [\'DELETE\',\'GET\',\'OPTIONS\',\'PATCH\',\'POST\',\'PUT\']\nRun Code Online (Sandbox Code Playgroud)\n\n在客户端,我尝试添加 \xe2\x80\x98\'Access-Control-Request-Method\xe2\x80\x99: \xe2\x80\x98PUT\xe2\x80\x99 标头,但这被拒绝浏览器。\xe2\x80\x99s 在客户端调用中注意到异常:
\n\n axios({\n method: \'put\',\n url: `${this.backendUrl}/api/assets/`,\n data: formData,\n headers: {\n \'Content-Type\': \'application/octet-stream\',\n }\n })\nRun Code Online (Sandbox Code Playgroud)\n\n另外,我\xe2\x80\x99m第一次尝试在Amazon AWS EC2上托管,所以也许有一些我不知道的必需的AWS配置。例如,是否需要使用API网关启用CORS?文档并没有这么说(\xe2\x80\x98如果您使用的是 API Gateway Import API,则可以使用 OpenAPI 文件\xe2\x80\x99 设置 CORS 支持)。
\n\n前端应用程序托管在具有以下 CORS 策略的 S3 存储桶上:
\n\n<?xml version="1.0" encoding="UTF-8"?>\n<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">\n<CORSRule>\n <AllowedOrigin>*</AllowedOrigin>\n <AllowedMethod>PUT</AllowedMethod>\n <AllowedMethod>POST</AllowedMethod>\n <AllowedMethod>GET</AllowedMethod>\n <MaxAgeSeconds>3000</MaxAgeSeconds>\n <AllowedHeader>*</AllowedHeader>\n</CORSRule>\n</CORSConfiguration>\nRun Code Online (Sandbox Code Playgroud)\n\n我在这里缺少什么?是否需要一些服务器端(尤其是 nginx)配置?
\n\n我尝试过的一些其他解决方案:
\n\n我怀疑请求/响应来源是否正确(例如 APPEND_SLASH 变量)。但如果是这种情况,\xe2\x80\x99 在本地托管时是否应该引发错误?
\n\n我也尝试像这个问题一样设置代理标头,但是如果不太了解 nginx,这注定会失败。
\n我通过改变三件事成功解决了这个问题:
\n\n我注意到AWS 文档指出:
\n\n\n\n\n已为 Amazon EC2 API 启用 CORS,并可供您使用。\n 您无需执行任何额外的配置步骤\n即可开始使用此功能。您调用 Amazon EC2 API 的方式没有变化;它们仍必须使用有效的 AWS 凭证进行签名,以确保 AWS 可以对请求者进行身份验证。[\xe2\x80\xa6]
\n
这通常由 AWS SDK 或 CLI 处理,但在我的例子中,我没有使用它们,所以我必须添加AWS_ACCESS_KEY_ID和AWS_SECRET_ACCESS_KEY。就我而言,我只是使用aws4 库:
axios(aws4.sign({\n accessKeyId: this.awsAccessKey,\n secretAccessKey: this.awsSecretAccessKey,\n method: \'put\',\n url: `${this.backendUrl}/api/assets/`,\n data: formData,\n body: JSON.stringify(formData),\n service: \'ec2\',\n region: \'eu-central-1\',\n path: \'/\',\n headers: {\n \'Content-Type\': \'application/octet-stream\'\n }\n }))\nRun Code Online (Sandbox Code Playgroud)\n\n不过,我\xe2\x80\x99已经看到了大量如何添加AWS Signature v.4而无需任何额外依赖的示例。
\n\n在 nginx 配置中,我将所有 add_headers 语句放入条件代码块中。想法来自这篇文章。
\n\nserver {\n listen 80;\n server_name [HOST_IP];\n\n location / {\n include proxy_params;\n proxy_pass http://unix:/home/ubuntu/[path_to_app]/app.sock;\n\n\n if ($request_method = \'OPTIONS\') {\n add_header \'Access-Control-Allow-Origin\' \'*\';\n add_header \'Access-Control-Allow-Methods\' \'GET, PUT, OPTIONS, POST, DELETE\';\n add_header \'Access-Control-Allow-Headers\' \'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Amz-Date\';\n add_header \'Access-Control-Max-Age\' 86400;\n add_header \'Content-Type\' \'text/html; charset=utf-8\';\n add_header \'Content-Length\' 0;\n return 204;\n }\n if ($request_method = \'PUT\') {\n add_header \'Access-Control-Allow-Methods\' \'GET, PUT, OPTIONS, POST, DELETE\';\n add_header \'Access-Control-Allow-Headers\' \'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Amz-Date\';\n add_header \'Access-Control-Expose-Headers\' \'Content-Length,Content-Range\';\n }\n if ($request_method = \'GET\') {\n add_header \'Access-Control-Allow-Origin\' \'*\';\n add_header \'Access-Control-Allow-Methods\' \'GET, PUT, OPTIONS, POST, DELETE\';\n add_header \'Access-Control-Allow-Headers\' \'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,X-Amz-Date\';\n add_header \'Access-Control-Expose-Headers\' \'Content-Length,Content-Range\';\n }\n }\n\n location /static/ {\n autoindex on;\n alias /home/ubuntu/analizy/be/site/static/;\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n在这里添加非默认标头就足够了。
\n\nfrom corsheaders.defaults import default_headers\nCORS_ALLOW_HEADERS = list(default_headers) + [\n \'X-Amz-Date\',\n]\nRun Code Online (Sandbox Code Playgroud)\n\n希望这会对某人有所帮助。
\n| 归档时间: |
|
| 查看次数: |
7573 次 |
| 最近记录: |