Laravel 4.1 身份验证会话数据不会跨请求持久化

Posted

技术标签:

【中文标题】Laravel 4.1 身份验证会话数据不会跨请求持久化【英文标题】:Laravel 4.1 authentication session data not persisting across requests 【发布时间】:2014-06-23 08:45:48 【问题描述】:

我有一个使用 eloquent 身份验证驱动程序和数据库会话驱动程序的 Laravel 4.1 应用程序。我的身份验证控制器成功运行 Auth::attempt 并重定向到新页面。但是,一旦在新页面上,身份验证会话数据似乎就消失了。我在重定向到的页面上运行了一个身份验证过滤器,但它失败了,然后再次将用户重定向到登录页面。用户永远不会通过登录页面。

这是我的 session.php

<?php
return array(
    'driver' => 'database',
    'lifetime' => 120,
    'expire_on_close' => true,
    'files' => storage_path().'/sessions',
    'connection' => 'mysql',
    'table' => 'sessions',
    'lottery' => array(2, 100),
    'cookie' => 'laravel_session',
    'path' => '/',
    'domain' => null,
    'secure' => false,
);

我的会话表架构:

CREATE TABLE `sessions` (
  `id` varchar(32) NOT NULL,
  `payload` text NOT NULL,
  `last_activity` int(11) NOT NULL,
  UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

还有我的身份验证过滤器:

Route::filter('auth', function()

    if (Auth::guest()) 
        if ( Request::ajax() ) 
            return Response::make("Your session has timed out.  Please sign in again.", 401);
         else 
            return Redirect::guest('login');
        
    
);

auth 过滤器中的 Auth::guest() 调用始终返回 false。

我在 Illuminate/Auth/Guard.php 的 user() 方法中添加了一些 Logging,发现在登录表单的 POST 中,当调用 user() 方法时,身份验证数据在会话中。但是,当它从重定向上的 auth 过滤器调用时(Auth::guest() 间接调用 user() 方法),会话数据消失了。

这里是user()方法,供参考:

public function user()

    if ($this->loggedOut) return;

    // If we have already retrieved the user for the current request we can just
    // return it back immediately. We do not want to pull the user data every
    // request into the method because that would tremendously slow an app.
    if ( ! is_null($this->user))
    
        return $this->user;
    

    $id = $this->session->get($this->getName());

    // First we will try to load the user using the identifier in the session if
    // one exists. Otherwise we will check for a "remember me" cookie in this
    // request, and if one exists, attempt to retrieve the user using that.
    $user = null;

    if ( ! is_null($id))
    
        $user = $this->provider->retrieveByID($id);
    

    // If the user is null, but we decrypt a "recaller" cookie we can attempt to
    // pull the user data on that cookie which serves as a remember cookie on
    // the application. Once we have a user we can return it to the caller.
    $recaller = $this->getRecaller();

    if (is_null($user) && ! is_null($recaller))
    
        $user = $this->getUserByRecaller($recaller);
    

    return $this->user = $user;

当从 auth 过滤器调用 user() 时,$this-&gt;loggedOut 为 false,但 $this-&gt;user 为 null,$this-&gt;session-&gt;get($this-&gt;getName()) 返回 null。

似乎在任何时候都没有调用 Auth::logout()。

【问题讨论】:

【参考方案1】:

会话表的 id 字段的长度需要至少为 40,因为 Laravel 使用 sha1 哈希作为会话 id。

【讨论】:

你刚刚拯救了我的一天,你是怎么找到它的? 如果我没记错的话,它已经到了在 Laravel 代码中发送垃圾日志消息的地步,并注意到正在记录的会话 ID 比我数据库中的会话 ID 长... 【参考方案2】:

我有一个类似的问题,当我将我的网站部署到数字海洋实例时,会话在请求之间没有持续存在,我花了几天时间寻找解决这个问题的答案,因为该网站在本地流浪者中运行良好机器。 我的问题的解决方案是在用户模型上,我必须将 getAuthPassword 函数返回语句从“$this->password”更改为“$this->Password”,它是数据库中的列名。

public function getAuthPassword()

    return $this->Password;

【讨论】:

以上是关于Laravel 4.1 身份验证会话数据不会跨请求持久化的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 4:股票身份验证登录不会跨页面持续存在

Laravel CSRF 保护

Laravel - 使用会话令牌进行身份验证

CSRF 保护

Laravel 会话数据不会跨页面加载

在 laravel 5.2 中使用默认身份验证路由对用户进行身份验证后设置会话数据