Joa*_*imB 33 django cors angularjs django-rest-framework django-cors-headers
我正在使用和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)
Run Code Online (Sandbox Code Playgroud)
.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 = '';
});
};
Run Code Online (Sandbox Code Playgroud)
}]);
谁有任何好的提示/想法/例子?
Vis*_*per 35
子域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的扩展名):
Run Code Online (Sandbox Code Playgroud)INSTALLED_APPS = ( ... 'corsheaders', ... ) MIDDLEWARE_CLASSES = ( ... 'django.middleware.csrf.CsrfViewMiddleware', ... 'corsheaders.middleware.CorsMiddleware', )
Run Code Online (Sandbox Code Playgroud)CORS_ORIGIN_WHITELIST = [ ... 'app.mydomain.com', ... ]
CORS_ALLOW_CREDENTIALS =真
将ensure_csrf_cookie装饰器添加到处理JSON API请求的视图中:
Run Code Online (Sandbox Code Playgroud)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文件:
Run Code Online (Sandbox Code Playgroud)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默认值:
Run Code Online (Sandbox Code Playgroud)$httpProvider.defaults.xsrfCookieName = 'csrftoken'; $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken'; $httpProvider.defaults.withCredentials = true;
再次注意withCredentials,这可确保在请求中使用CSRF Cookie.
下面我将展示如何使用AngularJS $ http服务和JQuery向api发出请求:
Run Code Online (Sandbox Code Playgroud)$http.post("http://api.mydomain.com/myresource", { field1 : ..., ... fieldN : ... }, { headers : { "x-csrftoken" : $cookies.csrftoken } });
另请参阅ngCookies模块.
使用JQuery(1.11.0):
Run Code Online (Sandbox Code Playgroud)$.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 } });
我希望这有帮助!!
Der*_*wok 15
直接来自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)
Run Code Online (Sandbox Code Playgroud)
$http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
Run Code Online (Sandbox Code Playgroud)
CORS_ALLOW_HEADERS = (
'x-requested-with',
'content-type',
'accept',
'origin',
'authorization',
'X-CSRFToken'
Run Code Online (Sandbox Code Playgroud)
)
而已!
此解决方案的一个小更新.
从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;
Run Code Online (Sandbox Code Playgroud)
这是由于1.2.9和1.2.10之间发生的以下变化 https://github.com/cironunes/angular.js/commit/781287473bc2e8ee67078c05b76242124dd43376
希望这有助于某人!
| 归档时间: |
|
| 查看次数: |
26693 次 |
| 最近记录: |