[英]AngularJS + Django Rest Framework + CORS ( CSRF Cookie not showing up in client )
我正在使用和Django Rest Framework + Django CORS Headers在AngularJS中開發一個1頁的應用程序。
我的問題是,當我聯系后端時,“csrftoken”cookie永遠不會出現在我的瀏覽器中。
例如:我正在使用帖子進行登錄。 我正確地獲得了“sessionid”cookie,但是“csrftoken”從未顯示出來,因此我無法從我的客戶端發出適當的帖子,因為我會因缺少csrf令牌而被拒絕。
前/后端的一些代碼片段。 這些是未完成的片段,所以不要掛在寫得不好的代碼上。
class LoginView(APIView):
renderer_classes = (JSONPRenderer, JSONRenderer)
def post(self, request, format=None):
serializer = LoginSerializer(data=request.DATA)
if serializer.is_valid():
userAuth = authenticate(username=serializer.data['username'], password=serializer.data['password'])
if userAuth:
if userAuth.is_active:
login(request, userAuth)
loggedInUser = AuthUserProfile.objects.get(pk=1)
serializer = UserProfileSerializer(loggedInUser)
user = [serializer.data, {'isLogged': True}]
else:
user = {'isLogged': False}
return Response(user, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
.controller('LoginCtrl', ['$scope', '$http', 'uService', '$rootScope', function(scope, $http, User, rootScope) {
scope.login = function() {
var config = {
method: 'POST',
withCredentials: true,
url: rootScope.apiURL+'/user/login/',
data : scope.loginForm
};
$http(config)
.success(function(data, status, headers, config) {
if (status == 200) {
console.log(data[0]); //Test code
// succefull login
User.isLogged = true;
User.username = data.username;
}
else {
console.log(data); //Test code
User.isLogged = false;
User.username = '';
}
})
.error(function(data, status, headers, config) {
console.log('Testing console error');
User.isLogged = false;
User.username = '';
});
};
}]);
誰有任何好的提示/想法/例子?
子域A上的AngularJS單頁Web應用程序,使用CORS和CSRF保護與子域B上的Django JSON(REST)API通信
由於我目前正在進行類似的設置,並且正在努力讓CORS與CSRF保護相結合,我想在這里分享我自己的經驗。
設置 - SPA和API都位於同一域的不同子域中:
AngularJS應用程序通過Django App在與Django API APP相同的項目中提供,以便設置CSRF Cookie。 例如,請參閱如何從一個Django項目運行多個網站
Django API應用程序 - 為了使CORS和CSRF保護工作,我需要在API后端執行以下操作。
在此應用程序的settings.py中(Django項目settings.py的擴展名):
INSTALLED_APPS = ( ... 'corsheaders', ... ) MIDDLEWARE_CLASSES = ( ... 'django.middleware.csrf.CsrfViewMiddleware', ... 'corsheaders.middleware.CorsMiddleware', )
CORS_ORIGIN_WHITELIST = [ ... 'app.mydomain.com', ... ]
CORS_ALLOW_CREDENTIALS =真
將ensure_csrf_cookie裝飾器添加到處理JSON API請求的視圖中:
from django.views.decorators.csrf import ensure_csrf_cookie @ensure_csrf_cookie def myResource(request): ...
用於AngularJS的Django App - AngularJS應用程序通過同一項目中的Django App提供。 這個Django應用程序設置為設置CSRF Cookie。 然后,來自cookie的CSRF令牌用於對API的請求(因此作為同一Django項目的一部分運行)。
請注意,幾乎所有與AngularJS應用程序相關的文件都只是Django透視圖中的靜態文件。 Django App只需要提供index.html來設置cookie。
在此應用程序的settings.py中(同樣是Django項目settings.py的擴展名),設置CSRF_COOKIE_DOMAIN,以便子域名也可以使用它們:
CSRF_COOKIE_DOMAIN =“。mydomain.com”
在views.py中,我只需要再次使用ensure_csrf_cookie裝飾器渲染AngularJS index.html文件:
from django.shortcuts import render from django.views.decorators.csrf import ensure_csrf_cookie # Create your views here. @ensure_csrf_cookie def index(request): return render(request, 'index.html')
使用AngularJS向API發送請求 - 在AngularJS App配置中設置以下$ httpProvider默認值:
$httpProvider.defaults.xsrfCookieName = 'csrftoken'; $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken'; $httpProvider.defaults.withCredentials = true;
再次注意withCredentials,這可確保在請求中使用CSRF Cookie。
下面我將展示如何使用AngularJS $ http服務和JQuery向api發出請求:
$http.post("http://api.mydomain.com/myresource", { field1 : ..., ... fieldN : ... }, { headers : { "x-csrftoken" : $cookies.csrftoken } });
另請參閱ngCookies模塊 。
使用JQuery(1.11.0):
$.ajax("http://api.mydomain.com/myresource", { type: 'POST', dataType : 'json', beforeSend : function(jqXHR, settings) { jqXHR.setRequestHeader("x-csrftoken", get_the_csrf_token_from_cookie()); }, cache : false, contentType : "application/json; charset=UTF-8", data : JSON.stringify({ field1 : ..., ... fieldN : ... }), xhrFields: { withCredentials: true } });
我希望這有幫助!!
直接來自docs https://docs.djangoproject.com/en/1.9/ref/csrf/#ajax
如果您的視圖未呈現包含csrf_token模板標記的模板,則Django可能不會設置CSRF令牌cookie。 這在表單動態添加到頁面的情況下很常見。 為了解決這種情況,Django提供了一個視圖裝飾器來強制設置cookie:ensure_csrf_cookie()。
由於您的應用程序是單頁面應用程序,因此可以將ensure_csrf_cookie()
添加到負責初始頁面加載的視圖中。
所以我找到了自己的解決方案,似乎工作得很好。
這是我的代碼的新片段:
class LoginView(APIView):
renderer_classes = (JSONPRenderer, JSONRenderer)
@method_decorator(ensure_csrf_cookie)
def post(self, request, format=None):
c = {}
c.update(csrf(request))
serializer = LoginSerializer(data=request.DATA)
if serializer.is_valid():
userAuth = authenticate(username=serializer.data['username'], password=serializer.data['password'])
if userAuth:
if userAuth.is_active:
login(request, userAuth)
loggedInUser = AuthUserProfile.objects.get(pk=1)
serializer = UserProfileSerializer(loggedInUser)
user = [serializer.data, {'isLogged': True}]
else:
user = {'isLogged': False}
return Response(user, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
$http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
CORS_ALLOW_HEADERS = (
'x-requested-with',
'content-type',
'accept',
'origin',
'authorization',
'X-CSRFToken'
)
而已!
此解決方案的一個小更新。
從AngularJS 1.2.10開始,您需要為客戶端中的每個請求類型設置CSRF cookie:
$http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
$http.defaults.headers.put['X-CSRFToken'] = $cookies.csrftoken;
$http.defaults.headers['delete']['X-CSRFToken'] = $cookies.csrftoken;
這是由於1.2.9和1.2.10之間發生的以下變化https://github.com/cironunes/angular.js/commit/781287473bc2e8ee67078c05b76242124dd43376
希望這有助於某人!
在So Much Search之后我登陸了這個解決方案,它的工作形成了我在本地系統和實時網絡派系服務器上這是我的Django用戶的解決方案請到你位於項目中的apache文件夾然后在bin中找到
<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>
然后在角度js應用程序,你只需要放置
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;
}]);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.