【问题标题】:Django CORS API from AngularJS来自 AngularJS 的 Django CORS API
【发布时间】:2016-03-23 20:19:15
【问题描述】:

我在 Django 中启用了 CORS,使用“django-cors”:

https://github.com/ottoyiu/django-cors-headers

按照这里的安装步骤,我设置了以下内容:

CORS_ORIGIN_ALLOW_ALL = False

CORS_ORIGIN_WHITELIST = (
    'http://localhost:8000'
)

django 应用在http://locahost:3000 上运行

我的前端是一个 Angular 应用程序,它在“http:/localhost:8000”上运行,我做了以下更改以与 django 应用程序通信。

RestangularProvider.setBaseUrl('http://localhost:3000/');

[将 Restangular 用于资源 API]

当我调用 GET API 时,会发生“OPTIONS”飞行前调用,并且我收到以下错误:

XMLHttpRequest 无法加载 http://localhost:3000/users。 Credentials 标志为“true”,但“Access-Control-Allow-Credentials”标头为“”。必须为“true”才能允许凭据。 Origin 'http://localhost:8000' 因此不允许访问。

查看文档,我了解到我需要设置服务器期望作为调用一部分的某些标头。所以,我添加了以下内容: RestangularProvider.setDefaultHeaders({"x-requested-with" : 'XMLHttpRequest'});

但是,在进行此更改时,我遇到了另一个错误,我无法解决: XMLHttpRequest 无法加载 http://localhost:3000/users。预检响应无效(重定向)

注意:请求/响应头如下:

General:
Remote Address:127.0.0.1:3000
Request URL:http://localhost:3000/users
Request Method:OPTIONS
Status Code:301 MOVED PERMANENTLY

Response Headers
Access-Control-Allow-Headers:x-requested-with, content-type, accept, origin, authorization, x-csrftoken, user-agent, accept-encoding
Access-Control-Allow-Methods:GET, POST, PUT, PATCH, DELETE, OPTIONS
Access-Control-Allow-Origin:http://localhost:8000
Access-Control-Max-Age:86400
Content-Type:text/html; charset=utf-8
Date:Thu, 17 Dec 2015 11:10:16 GMT
Location:http://localhost:3000/users/
Server:WSGIServer/0.1 Python/2.7.10
X-Frame-Options:SAMEORIGIN

Request Headers
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:accept, x-requested-with
Access-Control-Request-Method:GET
Cache-Control:no-cache
Connection:keep-alive
Host:localhost:3000
Origin:http://localhost:8000
Pragma:no-cache
Referer:http://localhost:8000/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36

【问题讨论】:

    标签: angularjs django cors django-cors-headers


    【解决方案1】:

    我终于设法解决了这个问题。问题是由于 API 命名不当造成的。

    我的同事将 API 命名如下:

    url(r'^users/', views.user_details)
    

    当我调用“/users”时,由于 django 的 APPEND_SLASH 设置,它会永久重定向到“/users/”。以下是 django 文档中关于 APPEND_SLASH 的说明:

    当设置为 True 时,如果请求 URL 不匹配 URLconf 中的任何模式并且它不以斜杠结尾,则会向附加斜杠的相同 URL 发出 HTTP 重定向。请注意,重定向可能会导致在 POST 请求中提交的任何数据丢失。

    APPEND_SLASH 设置仅在 CommonMiddleware 时使用 已安装。

    当然,解决此问题的最简单(也是最好)的方法是通过删除斜杠来更新 API url,即

    url(r'^users', views.user_details)
    

    那么它会直接匹配URL,并且不会发出重定向。

    但是,如果有人真的想在 API 中保留斜杠,那么您仍然可以通过在 AngularJS 中添加以下代码来使其工作:

    resourceProvider.defaults.stripTrailingSlashes = false;
    RestangularProvider.setRequestSuffix('/'); 
    

    以上不推荐,但既然是我实验出来的,我还是分享一下吧。

    【讨论】:

      【解决方案2】:

      CORS 会造成问题,就好像您在 Angular 应用程序中设置了 $httpProvider.defaults.withCredentials = true;。我尝试了很多解决方案,但经过长时间的搜索,这是我为您提供的解决方案,我相信它对您有用

      只需将此代码添加到您的 Django apache 配置文件中,它可能是 httpd.conf 文件(通常位于 *.conf 文件中,例如 httpd.conf 或 apache.conf),或在 .htaccess 中。然后只需添加此代码

      <IfModule mod_headers.c>
      SetEnvIf Origin (.*) AccessControlAllowOrigin=$1
      Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
      Header set Access-Control-Allow-Credentials true
      </IfModule> 
      

      或者如果它们是内置代码,则在该文件中找到您的文件夹目录,并且其中只有此代码

      SetEnvIf Origin (.*) AccessControlAllowOrigin=$1
          Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
          Header set Access-Control-Allow-Credentials true
      

      您还需要使用以下方法更改 Angular 应用程序配置

      angular.module('app', ['ngCookies'])
          .config([
         '$httpProvider',
         '$interpolateProvider',
         function($httpProvider, $interpolateProvider, $scope, $http) {
             $httpProvider.defaults.withCredentials = true;
             $httpProvider.defaults.xsrfCookieName = 'csrftoken';
             $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
         }]).
         run([
         '$http',
         '$cookies',
         function($http, $cookies) {
             $http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
         }]);
      

      【讨论】:

        【解决方案3】:

        我在https://github.com/ottoyiu/django-cors-headers/blob/1e7bf86310e54cf2520c1b197d4e54bf80004df3/corsheaders/middleware.py挖了一圈,发现可以用

        CORS_ALLOW_CREDENTIALS = True
        

        在 django settings.py 中

        这会将 Access-Control-Allow-Credentials 响应标头设置为 True

        我现在看到它甚至被记录在案:https://github.com/ottoyiu/django-cors-headers

        这帮我解决了

        【讨论】:

          【解决方案4】:

          不管怎样,django-cors 文档似乎只在 django 设置中使用主机名(而不是完整的 URL),例如:

          Example:
          
              CORS_ORIGIN_WHITELIST = (
                  'google.com',
                  'hostname.example.com'
              )
          
          
          Default:
          
              CORS_ORIGIN_WHITELIST = ()
          

          也许你可以尝试一个简单的东西,比如localhost,然后尝试如果有效,然后添加端口号并检查它是否仍然有效?

          【讨论】:

          • 如果您尝试使用 * 将所有域列入白名单怎么办?我用 django-cors 在我的一个项目上设置了这个,它按预期工作。
          • 也试过了,希望它能工作,但结果相同。我收到相同的错误“预检响应无效(重定向)”
          • 您是否按照in the documentation 的描述将 cors 添加到已安装的应用程序和中间件中?
          猜你喜欢
          • 2016-04-20
          • 2014-10-19
          • 2020-11-14
          • 2020-11-28
          • 2016-07-15
          • 2020-12-29
          • 1970-01-01
          • 2017-02-19
          • 1970-01-01
          相关资源
          最近更新 更多