Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Varnish - How to cache logged-in users

I installed varnish and everything works OK.

However, I have a need to cache logged-in users. This is what I have in my VCL:

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

sub vcl_recv {   
    unset req.http.Cookie;    
    if (req.http.Authorization || req.http.Cookie) {
        return (lookup);
    }
    return (lookup);
}

sub vcl_fetch {
    unset beresp.http.Set-Cookie;
    set beresp.ttl = 24h;
    return(deliver);
}

The above works but users can view other users data e.g. Say I'm logged in as Sam and access page A. When another user, say Angie, logins in and opens page A, she sees the same content as Sam.

Is there a way I can restrict pages to logged-in users who actually are authorized to view that page?

My request header is as follows:

Request Headersview source
Accept  text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding gzip, deflate
Accept-Language en-US,en;q=0.5
Authorization   Basic YWRtaW46YWRtaW4=
Connection  keep-alive
Cookie  tree-s="eJzTyCkw5NLIKTDiClZ3hANXW3WuAmOuRKCECUjWFEnWIyIdJGvGlQgEegAD3hAj"; __ac="0zVm7PLtpaeQUXtm9BeYrC5%2BzobmBLPQkjRtxjyRGHs1MGY1MTgzZGFkbWluIQ%3D%3D"; 'wc.cookiecredentials'="0241d135445f7ca0b1cb7aced45da4e750f5414dadmin!"

Can I use the Authorization entry on the request header to enforce this restriction?

like image 959
Frankline Avatar asked Sep 17 '25 23:09

Frankline


1 Answers

What your VCL is currently doing is removing Cookie from the request header and caching all requests. This causes the exact behavior you describe: the first page load is cached and all subsequent users get the cached content - no matter who makes the request. Generally you only want to cache content for users that have not logged in.

You cannot do authorization or access control using Varnish. This needs to be handled by the backend. In order to do this you need to identify the cookie that contains relevant session information and keep the cookie if a session is defined, and drop the cookie in other cases.

For example:

sub vcl_recv {
  if(req.http.Cookie) {
    # Care only about SESSION_COOKIE
    if (req.http.Cookie !~ "SESSION_COOKIE" ) {
      remove req.http.Cookie;
    }
  }
}

That way all requests that contain a "SESSION_COOKIE" cookie will be passed through to the backend while users that have not logged in receive a cached copy from Varnish.

If you wish to use Varnish for caching with logged in users as well, I'd suggest you take a look at Varnish's ESI features.

like image 166
Ketola Avatar answered Sep 22 '25 03:09

Ketola