Alexxosipov
Alexxosipov

Reputation: 1234

Laravel cookies comes with encryption, why?

I got the following serivce provider:

class CartServiceProvider extends ServiceProvider {
    public function boot() {

    }

    public function register() {
        $this->app->singleton(\Alexxosipov\Cart\Cart::class, function($app) {
            return new \Alexxosipov\Cart\Cart($app['request']);
        });
    }
}

And my Cart class, where I got this:

$this->id = (request()->cookie('cart_id')) ? request()->cookie('cart_id') : false;

But request()->cookie('cart_id') returns encrypted string. If I will do it in any controller, it works fine. Why? What should I do to use it in Cart class?Laravel 5.5

Upvotes: 1

Views: 3473

Answers (2)

Lionel Chan
Lionel Chan

Reputation: 8059

The sequences of Laravel bootstrapping a request is this (v5.6): (CMIIW)

  1. index.php is called
  2. \Illuminate\Foundation\Application created
  3. HttpKernel registered. This register your middlewares
  4. Console Kernel registered. This defines console commands
  5. Exception Handler registered. This defines exception handlers
  6. HttpKernel instantiated. This instantiate all middlewares, plus boot/register all your service providers
  7. Create global request instance. Pass it to HttpKernel to handle incoming request.
  8. Middleware EncryptCookies called, cookies decrypted
  9. Sending request to other middlewares to process
  10. Send request to router, router dispatch to controller
  11. ...
  12. Before sending response to browser, cookies encrypted back in EncryptCookies

Cookie is remained encrypted in Step 1 - Step 7. Your CartServiceProvider is trying to obtain a cookie that is yet to be decrypted at Step 6, which is not possible. Consider either

  1. Decrypt the cookie by yourself (using just decrypt), or

  2. Make a middleware to instantiate the cart after EncryptCookies. It's a little bit too early to instantiate cart at the bootstrapping service providers phase.


Edit: Add singleton suggestion

I think you could do this:

  1. Create a new method named loadCartFromRequest($request) in your Cart::class. This method help you load a cart instance from request during the middleware phase.

  2. In your CartServiceProvider, you register a singleton of Cart::class as usual, but no need to read the request here.

  3. Create a middleware, called CartMiddleware. This middleware call app(Cart::class)->loadCartFromRequest($request).

  4. Then at any other places that you need the cart instance, you can access your cart model from app(Cart::class).

I hope I understand your requirement correctly :)

Upvotes: 5

Devon Bessemer
Devon Bessemer

Reputation: 35337

Why? Cookie encryption protects data stored in the client's browser.

The How: Laravel uses the EncryptCookies middleware, this middleware would not yet be processed when your service provider is registered but would be processed for the controller since middlewares are in the routing stack before the request is passed to the controller.

Since I don't know about your cart class and its logic, I can't really recommend what you should do. Perhaps you need to think about when you are passing the Request object to your class.

Upvotes: 4

Related Questions