2013-09-23 53 views
4

我使用varnish作爲Django應用程序的前端緩存。關於VCL配置,它一切正常。我遇到的問題是,在用戶註銷csrftoken後,cookie不會被刪除,從此清漆就會有MISS響應而不是HIT。註銷後Django無法刪除csrftoken

backend default { 
    .host = "127.0.0.1"; 
    .port = "8000"; 
} 

sub vcl_recv { 
    set req.grace = 15s; 

    if (req.http.Cookie) { 
     set req.http.Cookie = regsuball(req.http.Cookie, "(^|;) *__utm.=[^;]+;? *", "\1"); # removes all cookies named __utm? (utma, utmb...) - tracking thing 
    } 

    # unless sessionid/csrftoken is in the request, don't pass ANY cookies (referral_source, utm, etc) 
    if (req.request == "GET" && (req.url ~ "^/static" || (req.http.cookie !~ "flash_sessionid" && req.http.cookie !~ "csrftoken"))) { 
     remove req.http.Cookie; 
    } 

    # normalize accept-encoding to account for different browsers 
    # see: https://www.varnish-cache.org/trac/wiki/VCLExampleNormalizeAcceptEncoding 
    if (req.http.Accept-Encoding) { 
     if (req.http.Accept-Encoding ~ "gzip") { 
      set req.http.Accept-Encoding = "gzip"; 
     } elsif (req.http.Accept-Encoding ~ "deflate") { 
      set req.http.Accept-Encoding = "deflate"; 
     } else { 
      # unknown algorithm 
      remove req.http.Accept-Encoding; 
     } 
    } 
} 

sub vcl_fetch { 
    set beresp.ttl = 300s; 
    set beresp.grace = 15s; 

    # static files always cached 
    if (req.url ~ "^/static") { 
     unset beresp.http.set-cookie; 
     return (deliver); 
    } 

    # pass through for anything with a session/csrftoken set 
    if (beresp.http.set-cookie ~ "flash_sessionid" || beresp.http.set-cookie ~ "csrftoken") { 
     return (hit_for_pass); 
    } else { 
     return (deliver); 
    } 
} 

sub vcl_deliver { 
    # Add a header to indicate a cache HIT/MISS 
    if (obj.hits > 0) { 
     set resp.http.X-Cache = "HIT"; 
    } else { 
     set resp.http.X-Cache = "MISS"; 
    } 
    return (deliver); 
} 
:這裏讀計算器上的一些相關的問題,我有這樣的退出瀏覽

def logout_view(request): 
    response = render_to_response('registration/logout.html', {}, context_instance=RequestContext(request)) 

    if request.user.is_authenticated(): 
     logout(request) 

     if request.GET.get('next', False): 
      response = HttpResponseRedirect(next) 

    response.delete_cookie('sessionid') 
    response.delete_cookie('csrftoken') 
    return response 

,這響應頭的用戶已經達到了註銷頁面

Response Headers 
Age:0 
Cache-Control:max-age=600 
Connection:keep-alive 
Content-Language:en 
Content-Type:text/html; charset=utf-8 
Date:Mon, 23 Sep 2013 09:20:43 GMT 
Expires:Mon, 23 Sep 2013 09:30:43 GMT 
P3P:CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT" 
Server:nginx/1.4.1 
Set-Cookie:sessionid=; expires=Thu, 01-Jan-1970 00:00:00 GMT; Max-Age=0; Path=/ 
Set-Cookie:csrftoken=; expires=Thu, 01-Jan-1970 00:00:00 GMT; Max-Age=0; Path=/ 
Transfer-Encoding:chunked 
Vary:Cookie, Accept-Language, Host 
Via:1.1 varnish 
X-Cache:MISS 
X-Varnish:1950616479 

default.vcl的完整性後後

在響應標題上,我看到Django將cookie值設置爲過去的日期,但是csrftoken cookie s直到堅持下一個請求。

我也嘗試刪除'django.middleware.csrf.CsrfViewMiddleware'中間件,但cookie仍然存在。

回答

1

您可以通過編輯vcl_fetch如下解決這個問題:

sub vcl_fetch { 
    # pass through for anything with a session/csrftoken set 
    if (beresp.http.set-cookie ~ "flash_sessionid" || beresp.http.set-cookie ~ "csrftoken" || beresp.http.set-cookie ~ "sessionid") { 
     return (hit_for_pass); 
    } else { 
     return (deliver); 
    } 
} 

這樣你的Set-Cookie:sessionid檢查爲好。

當使用beresp.http.set-cookie時,Varnish只能看到第一個Set-Cookie標題,所以在您的案例中,Varnish返回vcl_deliver而不是hit_for_pass。

爲了進一步閱讀,我建議看看vmod_header