fukamachi / clack

Web server abstraction layer for Common Lisp
MIT License
1.05k stars 86 forks source link

Clack.Middleware.Session creates a session every time #100

Open ralt opened 9 years ago

ralt commented 9 years ago

Hi,

If I wrap my app with Clack.Middleware.Session, a session is created for each user. Even if the user hasn't logged in, through any way.

Maybe I have missed something? If I haven't, then it's problematic.

The problem with this approach is that it's not compatible with reverse proxy cache solutions like varnish. A good way to use varnish, for example, is to cache pages and serve the same cache entry for all the anonymous users. To know that a user is anonymous, it just looks at the request cookies and see if no session cookie is present.

2 new methods could be added on the middleware: start and destroy. start would basically create the session cookie and hash table, and destroy would remove the session cookie and delete the associated data.

This way, the methods could be called manually in the route handlers, for example at login and logout time.

To maintain backwards compatibility, a new option could be added to the constructor.

Cheers, Florian

fukamachi commented 9 years ago

Clack.Middleware.Session adds a key :clack.session.options to env. It is a hash-table to communicate with the middleware.

It sees these keys -- :expire, :change-id and :no-store.

You should be able to prevent storing a session by (setf (gethash "no-store" (getf env :clack.session.options)) t).

(builder
  (lambda (app)
    (lambda (env)
      (prog1 (call app env)
        (unless (logined-p)
          (setf (gethash "no-store" (getf env :clack.session.options)) t)))))
  <clack-middleware-session>
  app)

... but it may be wrong with the code. I'm looking into it.

ralt commented 9 years ago

Well, I want to store the session at some point. Just... being able to start and stop the storing. And send the matching cookies...

fukamachi commented 9 years ago

The middleware would be better to have an option for preventing sending "Set-Cookie" header if the session is empty. Doesn't it suit your case?

ralt commented 9 years ago

Well, if I can create the session (and clack will send the set-cookie), and destroy it (and clack will send the set-cookie), then yes, it suits my case.

ralt commented 9 years ago

I'm not sure I completely understood what you said, but here is the ideal scenario:

Is that what you had in mind?

fukamachi commented 9 years ago

I think it would be nice if it doesn't send Set-Cookie header when "no-store" is non-NIL. However, I'm not willing to change the default behaviour from "I'm setting it to every request" to "I'll set it if you tell me".

Needless to say, but you can write your own session management middleware to do it.

ghost commented 8 years ago

It would be really helpful if the Set-Cookie header was missing when the session is empty. As there is the cookie law in EU, we need to ask before setting any cookies. This compliance becomes easy when the first cookie set by default is the acceptance of the use of cookies and not the arrival to the site. The acceptance of the use of cookies can also be made implicit by simply showing a message that the site uses cookies and by using functions requiring cookies, the user accepts the use of cookies. However, the acceptance can not occur before this text is displayed.

How can I do this?

dkochmanski commented 6 years ago

@tsill European law doesn't ban all cookies if no consent is asked or provided. Session management and similar are not subject of this law. Please compare with: http://ec.europa.eu/ipg/basics/legal/cookies/index_en.htm

fukamachi commented 6 years ago

Clack v1 is deperecated. Lack is a successor of it.

Lack.Middleware.Session has :keep-empty option for choosing if sending the Set-Cookie header when the session is empty. (Default is T)