来自 AngularJS 的 Django CORS API
Django CORS API from AngularJS
我在 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/');
[对资源 APIs 使用 Restangular]
当我调用 GET API 时,发生了 "OPTIONS" pre-flight 调用,并且出现以下错误:
XMLHttpRequest 无法加载 http://localhost:3000/users. Credentials flag is 'true', but the 'Access-Control-Allow-Credentials' header is ''. It must be 'true' to allow credentials. Origin 'http://localhost:8000' 因此不允许访问。
查看文档后,我了解到我需要设置某些 headers 服务器希望将其作为调用的一部分。所以,我添加了以下内容:
RestangularProvider.setDefaultHeaders({"x-requested-with" : 'XMLHttpRequest'});
但是,在进行此更改时,我遇到了另一个错误,我无法解决该错误:
XMLHttpRequest 无法加载 http://localhost:3000/users。预检响应无效(重定向)
注:request/responseheaders如下:
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
就其价值而言,django-cors 文档似乎只在 django 设置中使用主机名(而不是完整的 URL),例如:
Example:
CORS_ORIGIN_WHITELIST = (
'google.com',
'hostname.example.com'
)
Default:
CORS_ORIGIN_WHITELIST = ()
也许你可以尝试一个简单的东西,比如localhost
,然后尝试如果有效,然后添加端口号并检查它是否仍然有效?
我终于设法解决了这个问题。问题是因为 API 命名不当。
我的同事将 API 命名为:
url(r'^users/', views.user_details)
当我调用“/users”时,由于 django 的 APPEND_SLASH 设置,它会永久重定向到“/users/”。这是 django 文档中关于 APPEND_SLASH:
的内容
设置为 True 时,如果请求 URL 与 URLconf 中的任何模式都不匹配,并且不以斜线结尾,则向相同的 URL 附加了一个斜杠。请注意,重定向可能会导致在 POST 请求中提交的任何数据丢失。
APPEND_SLASH
设置仅在 CommonMiddleware
时使用
已安装。
当然,解决这个问题的最简单(也是最好)的方法是通过删除斜杠来更新 API url,即
url(r'^users', views.user_details)
那么它会直接匹配URL,不会发出重定向。
但是,如果有人真的想在 API 中保留尾部斜杠,那么您仍然可以通过在 AngularJS 中添加以下代码来使其工作:
resourceProvider.defaults.stripTrailingSlashes = false;
RestangularProvider.setRequestSuffix('/');
以上不推荐,但由于是我实验出来的,所以还是分享一下。
我在 https://github.com/ottoyiu/django-cors-headers/blob/1e7bf86310e54cf2520c1b197d4e54bf80004df3/corsheaders/middleware.py 中搜索了一下,发现可以使用
CORS_ALLOW_CREDENTIALS = True
在 Django 中 settings.py
这会将 Access-Control-Allow-Credentials 响应 header 设置为 True
我现在看到它甚至被记录在案:https://github.com/ottoyiu/django-cors-headers
帮我解决了
这 CORS 会产生问题,就像您在 angular 应用中设置 $httpProvider.defaults.withCredentials = true;
一样。我尝试了很多次很多解决方案,但经过长时间的搜索,这是我为您提供的解决方案,我相信它对您有用
只需将此代码添加到您的 Django apache 配置文件中,它可能是 httpd.conf 文件(通常位于 *.conf 文件中,例如 httpd.conf 或 apache.conf),或者在 .htaccess 中。然后只需添加此代码
<IfModule mod_headers.c>
SetEnvIf Origin (.*) AccessControlAllowOrigin=
Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
Header set Access-Control-Allow-Credentials true
</IfModule>
或者如果它们是内置代码,则在该文件中找到您的文件夹目录,并且其中只有这段代码
SetEnvIf Origin (.*) AccessControlAllowOrigin=
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;
}]);
我在 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/');
[对资源 APIs 使用 Restangular]
当我调用 GET API 时,发生了 "OPTIONS" pre-flight 调用,并且出现以下错误:
XMLHttpRequest 无法加载 http://localhost:3000/users. Credentials flag is 'true', but the 'Access-Control-Allow-Credentials' header is ''. It must be 'true' to allow credentials. Origin 'http://localhost:8000' 因此不允许访问。
查看文档后,我了解到我需要设置某些 headers 服务器希望将其作为调用的一部分。所以,我添加了以下内容: RestangularProvider.setDefaultHeaders({"x-requested-with" : 'XMLHttpRequest'});
但是,在进行此更改时,我遇到了另一个错误,我无法解决该错误: XMLHttpRequest 无法加载 http://localhost:3000/users。预检响应无效(重定向)
注:request/responseheaders如下:
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
就其价值而言,django-cors 文档似乎只在 django 设置中使用主机名(而不是完整的 URL),例如:
Example:
CORS_ORIGIN_WHITELIST = (
'google.com',
'hostname.example.com'
)
Default:
CORS_ORIGIN_WHITELIST = ()
也许你可以尝试一个简单的东西,比如localhost
,然后尝试如果有效,然后添加端口号并检查它是否仍然有效?
我终于设法解决了这个问题。问题是因为 API 命名不当。
我的同事将 API 命名为:
url(r'^users/', views.user_details)
当我调用“/users”时,由于 django 的 APPEND_SLASH 设置,它会永久重定向到“/users/”。这是 django 文档中关于 APPEND_SLASH:
的内容设置为 True 时,如果请求 URL 与 URLconf 中的任何模式都不匹配,并且不以斜线结尾,则向相同的 URL 附加了一个斜杠。请注意,重定向可能会导致在 POST 请求中提交的任何数据丢失。
APPEND_SLASH
设置仅在 CommonMiddleware
时使用
已安装。
当然,解决这个问题的最简单(也是最好)的方法是通过删除斜杠来更新 API url,即
url(r'^users', views.user_details)
那么它会直接匹配URL,不会发出重定向。
但是,如果有人真的想在 API 中保留尾部斜杠,那么您仍然可以通过在 AngularJS 中添加以下代码来使其工作:
resourceProvider.defaults.stripTrailingSlashes = false;
RestangularProvider.setRequestSuffix('/');
以上不推荐,但由于是我实验出来的,所以还是分享一下。
我在 https://github.com/ottoyiu/django-cors-headers/blob/1e7bf86310e54cf2520c1b197d4e54bf80004df3/corsheaders/middleware.py 中搜索了一下,发现可以使用
CORS_ALLOW_CREDENTIALS = True
在 Django 中 settings.py
这会将 Access-Control-Allow-Credentials 响应 header 设置为 True
我现在看到它甚至被记录在案:https://github.com/ottoyiu/django-cors-headers
帮我解决了
这 CORS 会产生问题,就像您在 angular 应用中设置 $httpProvider.defaults.withCredentials = true;
一样。我尝试了很多次很多解决方案,但经过长时间的搜索,这是我为您提供的解决方案,我相信它对您有用
只需将此代码添加到您的 Django apache 配置文件中,它可能是 httpd.conf 文件(通常位于 *.conf 文件中,例如 httpd.conf 或 apache.conf),或者在 .htaccess 中。然后只需添加此代码
<IfModule mod_headers.c>
SetEnvIf Origin (.*) AccessControlAllowOrigin=
Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
Header set Access-Control-Allow-Credentials true
</IfModule>
或者如果它们是内置代码,则在该文件中找到您的文件夹目录,并且其中只有这段代码
SetEnvIf Origin (.*) AccessControlAllowOrigin=
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;
}]);