【发布时间】:2014-01-06 22:48:53
【问题描述】:
我在成功登录和注销后尝试登录时收到状态代码 403。
客户端用 Angular 编写,服务器端用 Django。
如下:
- 客户端请求 url
'/'使用所有必需的静态文件(角度、引导程序、jQuery 源和我定义的角度源)获取主 HTML 模板<div ng-view></div>将插入更多模板的标签。 - 通过 $location 服务被重定向到 url
'/#/login' -
$routeProvider中的这条规则在'/#/login'被命中后执行:$routeProvider.when('/login', { templateUrl: 'login.html' }); -
'login.html'由 django 视图提供服务,用于登录的表单呈现给用户 - 用户登录成功并提供正确的凭据
- 然后用户通过单击一个按钮注销,该按钮触发
'$http.get( '/logout/' );',然后重定向到url'/#/login' - 这就是问题所在。当用户填写凭证表单并发送
'POST'请求时,返回403。我认为是这样,因为此路由仅由角度完成,并且由于已经请求'login.html'模板,因此它已被捕获并且可以在不打后端的情况下提供服务,但是在注销后当前拥有的 CSRF cookie 已过时,所以这就是为什么我收到 403。所以我尝试删除该模板:
logout: function(){
var forceLoginTemplateRequest = function(){
if( $templateCache.get('login.html') !== 'undefined'){
$templateCache.remove('login.html');
}
};
var responsePromise = $http.get(
urls.logout
);
responsePromise.success(forceLoginTemplateRequest);
return responsePromise;
}
这样做之后,我可以看到客户端在注销后总是请求'login.html' 模板,所以我认为我可以在从后端提供该模板时提供 CSRF cookie:
#urls.py
urlpatterns = patterns(
'',
...
url(r'^$', serve_home_template),
url(r'^login.html$', serve_login_template),
url(r'^login/', login_view, name='login'),
url(r'^logout/', logout_view, name='logout'),
...
)
#views.py
@ensure_csrf_cookie
def serve_login_template(request):
return render(request, "login.html")
@ensure_csrf_cookie
def serve_home_template(request):
return render(request, 'home.html')
但它仍然不起作用,我在注销后尝试登录时收到 403。我管理它工作的唯一方法是简单地刷新页面,以便从后端再次请求每个文件,无论是模板还是源文件,并使用它们更新 CSRF cookie。
这是我的应用程序的运行部分,用于确保每次请求都发送 CSRF cookie:
mainModule.run(['$http','$cookies', '$location', '$rootScope', 'AuthService', '$templateCache',
function($http, $cookies, $location, $rootScope, AuthService, $templateCache) {
$http.defaults.headers.common['X-CSRFToken'] = $cookies.csrftoken;
$rootScope.$on( "$routeChangeStart", function(event, next, current) {
if ( !(AuthService.isLoggedIn() == "true")){
$location.path('/login');
}
});
}]);
【问题讨论】:
-
能否请您粘贴来自 chrome 开发工具或类似工具的请求和响应标头。
-
@JoakimB 无论有没有 Django-template-system,您仍然需要 CSRF 令牌/cookie 来与 API 交互,因此模板系统与我遇到的问题没有任何关系。
-
我没有说这与问题有关,这是一个简单的提示 :) 请求/响应标头仍然有助于解决发生的问题
标签: ajax django angularjs csrf django-csrf