Reputation: 40985
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?
Upvotes: 4
Views: 6384
Reputation: 345
It can be done through the vcl only - with the addition of a vmod or inline C.
A simple example: Let's say you have three different pages for three different levels of users: (not logged in, logged in, admin) and the level is stored in the cookie. You can take the cookie value and add a get parameter to the url:
http://example.com/homepage.html?user_level=none
http://example.com/homepage.html?user_level=logged_in
http://example.com/homepage.html?user_level=admin
(Your vmod would handle either adding '?' or '&' and the name value pair to the end of the URL.)
All of this would normally be done in a vmod but it could also be done, depending upon the size, as inline C. Vmods are preferred but inline C can get you up and running for initial testing - then move to a vmod.
When vcl_hash() runs it will hash over the url that your just modified. The Varnish cache will now contain up to three different versions of the page. From Varnish's point of view these are three different cache objects. You can set a different TTL for each variation of the page.
On a cache miss, the backend web server can either ignore this get param that you just added or you can remove it within the vcl, in vcl_hash() or vcl_backend_fetch. Your backend server would typically use the cookie value and not this vcl added parameter.
In summary, you are altering the URL parameters so that it hashes differently for the different user-levels that you need. Alternatively, you can just change your vcl_hash() method to hash over cookie values instead but I find altering the URL better for varnishncsa logging and reporting. In addition, if the cookie is encrypted then PURGE requests can be handled easier with basic cURL requests when you simply modify the URL parameters. Your PURGE conditional will handle if the client sending the PURGE requests is an authorized user.
Upvotes: 0
Reputation: 2767
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.
Upvotes: 3