nette / application

🏆 A full-stack component-based MVC kernel for PHP that helps you write powerful and modern web applications. Write less, have cleaner code and your work will bring you joy.
https://doc.nette.org/application
Other
405 stars 103 forks source link

Session-less store/restoreRequest #302

Open mabar opened 2 years ago

mabar commented 2 years ago

Current implementation of Presenter->store/restoreRequest() uses session for storage.

Pluses are:

Minuses are:

So an ideal implementation should not start session, keep phishing protection, add protection agains spamming session storage with useless data and yet, keep the forms re-submit working.


What are (not) possible implementations?


So what is possible? I think we need an interface to allow alternative storages which can drop expired keys immediatelly:

interface RequestStorage
{

  /**
   * @return Globally unique request ID
   */
  public function store(Request $request, \DateTimeInterface $expiration): string;

  public function restore(string $requestId): ?Request;

}

Alternative could be to introduce SessionStorage interface in nette/http. Such interface would accept expiration time of session key and pass it to underlying storage, which could delete key immediatelly after expiration and not wait for another user request. Worst case scenario with such storage is that an empty session remains until session itself expires.


To store request body only when needed, Presenter->storeRequest() could have a parameter bool $keepRequestBody = true. In my case I would store request body only if $this->firewall->getLastExpiredLogin()) !== null is true. Only users who were already logged in would have whole request saved, not newcomers, whose could be bots. Implementation for nette/security users should be quite similar.


While it does not solve the problem perfectly, it allows developers to reduce it to bare minimum and have control over it. And it could remain backward compatible with current implementation in Presenter.

JanTvrdik commented 2 years ago

Instead of session could be used e.g. redis

I don't understand. If you can use redis for request storage, why are you not using redis for sessions?

mabar commented 2 years ago

@JanTvrdik Problem is native session mechanism itself is not enough to delete session keys immediately after expiration. While the stored request lifetime is just 10 minutes, session itself can exist for weeks and the key is not deleted until session expires or Nette uses this session.