当切换协议(https到http或http到https)时,Laravel会话不工作


Laravel session not working when switching protocol (https to http or http to https)

我目前正在开发一个应用程序,我必须使用SSL保护几个页面。例如:登录、注册页面。但是,当协议在httpshttp之间切换时,Laravel会话不通过HTTP传输。

是否有解决方案,Laravel将保留两个协议的会话

默认情况下,Laravel为认证和会话cookie设置了secure和/或httponly。我找不到在配置中改变这一点的方法,事实上在Laravel 4.0中(这不再是这种情况),httponly是硬编码为vendor/laravel/framework/src/Illuminate/Session/SessionManager.php

中的设置。

注意,你不应该泄漏cookie从HTTPS到HTTP,因为它阻止你能够保持会话安全(我仍然可以嗅探会话从另一个用户在我的网络上登录到你的网站,例如)。

<标题> Laravel 4.1 +

编辑app/config/session.php。如果您希望在https上设置的cookie也可以在http上读取,请将'secure'密钥更改为false。

或者,按照@martinstoeckli的建议,根据环境的值设置键。

<标题> Laravel 4.0

也许实现这一点的最好方法是用你自己的处理程序替换CookieSessionHandler

例如,可以创建一个新类,它将扩展CookieSessionHandler,并使用更新的write函数,该函数将所有cookie标记为不用于https/http。

Class NewCookieSessionHandler extends CookieSessionHandler implements 'SessionHandlerInterface {
    /**
     * {@inheritDoc}
     */
    public function write($sessionId, $data)
    {
        // $this->cookie is 'Illuminate'Cookie'CookieJar
        $this->setCookie($this->cookie->make($sessionId, $data, $this->minutes, '/', false, false));
    }
    /**
     * Set the given cookie in the headers.
     *
     * @param  'Symfony'Component'HttpFoundation'Cookie  $cookie
     * @return void
     */
    protected function setCookie($cookie)
    {
        if (headers_sent()) return;
        setcookie($cookie->getName(), $cookie->getValue(), $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), false, false);
    }
    
}

然后在app/config/session.php中,您可以将驱动程序更改为NewCookie

,最后在app/start/global.php中注册新的cookie驱动程序,覆盖设置cookie

use Illuminate'Cache'Repository;
Cookie::extend('NewCookie', function($app)
{
    return new NewCookieSessionHandler;
});

这不仅仅是Laravel的问题。您必须决定包含会话id的cookie是否仅限于HTTPS,或者您是否也将其发送到HTTP页面。

  • 如果cookie被限制为HTTPS页面,它将不会被发送浏览器拒绝不安全的HTTP请求。在这种情况下,你会失去
  • 如果cookie被发送到HTTPS和HTTP页面,攻击者可以读取会话id,从而冒充用户,当他可以监听HTTP请求时。cookie不仅会随html请求一起发送,还会随图片和其他资源的每个请求一起发送。

该配置可以在'app'config'session.php文件中找到,称为secure。如果您希望仅在活动站点上将其设置为true(而不是用于开发),您可以这样写:

'secure' => App::environment('production'),

要处理这个问题,您必须将两个关注点分开,维护会话和身份验证。我用示例代码写了一篇关于这个主题的小文章。请记住,当您在协议之间切换时,您总是容易受到ssl条攻击,因此您可以考虑对整个站点使用HTTPS。对于今天的服务器,这应该不再是一个问题。