Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ajax/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ajax Django角度身份验证CSRF缓存模板_Ajax_Django_Angularjs_Csrf_Django Csrf - Fatal编程技术网

Ajax Django角度身份验证CSRF缓存模板

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”{

在成功登录和注销后尝试登录时,我收到状态代码403

客户端用Angular编写,服务器端用Django编写

具体如下:

  • 客户端请求url
    “/”
    获取主HTML模板,其中包含所有必需的静态文件(angular、bootstrap、jQuery源和我定义的angular源)
    标记,将在其中插入更多模板
  • Via$location服务被重定向到url
    “/#/login”
  • 点击
    '/#/login'
    后,将执行
    $routeProvider
    中的此规则:
    $routeProvider.when(“/login”{
    templateUrl:'login.html'
    });
  • 'login.html'
    由django视图提供,用于登录的表单呈现给用户
  • 用户通过提供正确的凭据成功登录
  • 然后用户通过单击一个按钮退出,该按钮将激发
    '$http.get(
    “/注销/”
    );'“/#/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})