在Laravel 4 API中完全禁用cookies

10

我正在使用Laravel来构建RESTful API。我使用基本的HTTP身份验证(Authenticate header),并使用以下过滤器:

Route::filter('auth', function()
{
    $credentials = ['email' => Request::getUser(), 'password' => Request::getPassword()];

    if (!Auth::once($credentials)) {
        $response   = ['error' => true, 'message' => 'Unauthorized request'];
        $code       = 401;
        $headers    = ['WWW-Authenticate' => 'Basic'];

        return Response::json($response, $code, $headers);
    }
});

它能正常工作,但是Laravel接下来会尝试为用户设置一个cookie(发送一个Set-Cookie头)。我尝试将session.driver配置键设置为array,但结果发现它现在会发送一个Set-Cookie: laravel_session=deleted的东西。

我该如何完全禁用这个Set-Cookie头呢?

谢谢。


你尝试过Laravel 4的本地基本身份验证过滤器auth.basic吗? - Muhammad Usman
@Usman 是的,它的工作方式几乎相同,除了它会发送一个 WWW-Authenticate 响应头,这不是我想要的。它还设置了 laravel_session cookie。 - Iso
将来参考 - 在Laravel 5中,只需使用数组进行会话存储,并在config/app.php中禁用cookie支持。不要忘记使用artisan清除编译。 - gidmanma
7个回答

15

对于无状态API,没有cookie和干净的标头,以下内容有效:

Route::filter('auth.basic', function()
{
    Config::set('session.driver', 'array');
    return Auth::onceBasic();
});
请注意,上述内容使用的是 Auth::onceBasic() 方法,但不知何故仍会发送 "Set-Cookie" 标头。根据文档,onceBasic 身份验证是无状态的;也许发送 cookie 是为了信息目的,是调试模式的副作用,或者可能是一个错误。无论哪种方式,仍然需要使用 Config::set(...) 。对于使用此过滤器的路由进行快速 curl 操作返回以下标头:
HTTP/1.1 200 OK
Date: Wed, 12 Feb 2014 02:34:26 GMT
Server: Apache/2.4.6 (Ubuntu)
X-Powered-By: PHP/5.5.3
Cache-Control: no-cache
X-Frame-Options: SAMEORIGIN
Transfer-Encoding: chunked
Content-Type: application/json

Auth::onceBasic() 看起来是一个适用于无状态 REST API 的好方法。在这种方法中,每个客户端请求都经过身份验证,并且不使用会话 cookie。

注意:上述筛选器未捕获的其他路由仍将设置 cookie(并发送“Set-Cookie”头)。因此,此解决方案适用于既有无状态 API 又有有状态 Web 访问/管理的常见情况。


6

要在 Laravel 4 控制器中禁用所有路由的会话,可以在类构造函数中设置会话驱动选项:

<?php

class ExampleController extends BaseController {

    public function __construct()
    {
        Config::set('session.driver', 'array');
    }

    public function getExample()
    {
        return "This example response should have no session cookie.";
    }

}

2

在 Laravel 4 和 4.2 中,您需要按照以下方式创建过滤器

Route::filter('no.session.cookie', function()
{
    Config::set('session.driver', 'array');
    Config::set('cookie.driver', 'array');
});

在laravel 5和5.1中,设置中间件handle()的方式如下:
public function handle($request, Closure $next){
  \Config::set('session.driver', 'array');
  \Config::set('cookie.driver', 'array');
 return $next($request);
}

2
尝试这个-虽然不太规范,但对我很有效。
此示例适用于单个路由,可以修改以管理路由前缀等。
首先,在app/config中创建一个目录以针对特定环境,例如stateless
然后,在app/config/stateless中放置一个session.php文件,并添加以下代码:
<?php
return array(
    'driver' => 'array'
);

最后,修改 bootstrap/start.php 中的 detectEnvironment 部分:

$env = $app->detectEnvironment(function()
{
    if ($_SERVER['REQUEST_URI'] == '/your/route') return 'stateless';
});

0

我正在使用Laravel开发API,因此肯定不想使用cookies。但是,对于需要身份验证的API,我确实希望使用会话机制。

因此,我使用了 sessions.driver = "file" 以便能够使用该机制,但又允许覆盖cookie设置。在进行了大量调试后,我发现中间件类中存在某些硬编码问题,但通过过滤器的魔法,您可以在设置cookie之前禁用该功能。

因此,在 filters.php 中,我创建了以下过滤器,并将其作为我的路由组的after过滤器添加。

/*
|--------------------------------------------------------------------------
| Custom Filter to remove the session cookie
|--------------------------------------------------------------------------
|
| By default, if session driver is other than `null` or `array`, it will
| create a cookie and pass the encrypted session id so that it can be used
| across web requests.
| However, since our application is an API, we dont need the cookie, but
| we still want to be able to use the session functionality, so to allow
| this, we just need to set the driver to `array` right before the 
| dispatcher gets to the point to add the session cookie.
| 
| This is the Laravel call stack
| \Illuminate\Session\Middleware::handle()
|   -> \Illuminate\Session\Middleware::addCookieToResponse()
|        -> \Illuminate\Session\Middleware::sessionIsPersistent()
|
| All session handling and file storage has happened before sessionIsPersistent()
| is called, so we are safe to add an `after` filter that will reset
| the driver in the configuration and thus preventing this specific
| cookie to be added, all other previously added cookies will be 
| kept (if any added) and thus sent as part of the response.
*/
Route::filter('session.cookie.remove', function(){
    // Has to be 'array' because null, will prevent from writing sessions
    Config::set('session.driver', 'array');
});

注意: 这个过滤器不会在发生异常时被调用,从而产生cookie,你可能需要在错误处理程序的配置上更新它(如果你没有覆盖Laravel的默认错误处理程序)。 要进行覆盖,请查看app/start/global.php


0

从您的app.php文件中的providers数组中删除'Illuminate\Cookie\CookieServiceProvider',即可解决问题 :)


不行,现在我遇到了一个“ReflectionException”: “Class cookie does not exist”(在 bootstrap/compiled.php 中)。看起来它源自于 vendor/laravel/framework/src/Illuminate/Auth/AuthManager.php:20: $guard->setCookieJar($this->app['cookie']);。还是谢谢你的帮助! - Iso
嗯...如果移除Session提供者会发生什么呢?我曾经在过去做过这个技巧,但我记不起来了!:( - ipalaus
1
同样的事情也发生在“类会话”中。您确定移除提供程序是正确的方法吗? - Iso
当编译文件中的某些内容似乎产生错误时,清除该文件可能是一个很好的主意,例如使用 artisan clear:compiled - imme

-1
你应该修改 session.php 文件:
<?php
return array(
    'driver' => isset($_SERVER['REQUEST_URI']) && (stripos($_SERVER['REQUEST_URI'], '/api') === 0) ? 'array' : 'native'
);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接