Ajax Django角度身份验证CSRF缓存模板
在成功登录和注销后尝试登录时,我收到状态代码403 客户端用Angular编写,服务器端用Django编写 具体如下:Ajax Django角度身份验证CSRF缓存模板,ajax,django,angularjs,csrf,django-csrf,Ajax,Django,Angularjs,Csrf,Django Csrf,在成功登录和注销后尝试登录时,我收到状态代码403 客户端用Angular编写,服务器端用Django编写 具体如下: 客户端请求url“/”获取主HTML模板,其中包含所有必需的静态文件(angular、bootstrap、jQuery源和我定义的angular源) 标记,将在其中插入更多模板 Via$location服务被重定向到url“/#/login” 点击'/#/login'后,将执行$routeProvider中的此规则: $routeProvider.when(“/login”{
“/”
获取主HTML模板,其中包含所有必需的静态文件(angular、bootstrap、jQuery源和我定义的angular源)
标记,将在其中插入更多模板“/#/login”
'/#/login'
后,将执行$routeProvider
中的此规则:
$routeProvider.when(“/login”{
templateUrl:'login.html'
});代码>
'login.html'
由django视图提供,用于登录的表单呈现给用户'$http.get(
“/注销/”
);'然后被重定向到url“/#/login”
'POST'
请求时,返回403。我认为是这样的,因为这个路由只由angular完成,而且由于'login.html'
模板已经被请求,它已经被捕获并且可以在不点击后端的情况下提供,但是在注销之后,当前拥有的CSRF cookie已经过时,所以这就是我得到403的原因。因此,我尝试删除该模板:'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');
}
});
}]);
这可能是缓存问题。尝试将
never\u缓存
装饰器添加到所有视图中:
from django.views.decorators.cache import never_cache
...
@ensure_csrf_cookie
@never_cache
def serve_login_template(request):
return render(request, "login.html")
...
我通过在
$routeChangeStart
事件中设置X-CSRFTOKEN
头来解决这个问题。
我不知道module.run阶段是如何工作的,但似乎当其中定义的某个事件发生时,该事件处理程序体之外定义的所有内容都不会执行
mainModule.run(['$http','$cookies', '$location', '$rootScope', 'AuthService',
function($http, $cookies, $location, $rootScope, AuthService) {
$http.defaults.headers.common['X-CSRFToken'] = $cookies.csrftoken;
$rootScope.$on( "$routeChangeStart", function(event, next, current) {
// Added this line
$http.defaults.headers.common['X-CSRFToken'] = $cookies.csrftoken;
if ( !(AuthService.isLoggedIn() == "true")){
$location.path('/login');
}
});
}]);
这与从$templateCache
中删除'login.html'
模板一起工作
除了使用$templateCache
服务删除客户端上的模板外,还可以将服务器设置为服务模板,并设置以下标题:
Cache-Control: no-cache, no-store, must-revalidate
Pragma : no-cache
Expires : 0
处理此问题的另一种方法是简单地强制页面刷新,但我不喜欢这种方法,因为这不是专业的单页应用程序方法。:) 一种解决方案是直接从cookie中读取当前的、新鲜的csrftoken,然后使用javascript更新过时的cookie
var fresh_token = document.cookie.match('csrftoken=([a-zA-Z0-9]{32})
这也没用。你能从chrome dev tools或类似软件中粘贴请求和响应头吗。@JoakimB有没有Django模板系统,你仍然需要CSRF令牌/cookie与API交互,所以模板系统与我遇到的问题没有任何关系。我没有说这与问题有任何关系,这是一个简单的提示:)仍然是一个req/响应头将有助于解决发生的问题
var fresh_token = document.cookie.match('csrftoken=([a-zA-Z0-9]{32})