【发布时间】:2015-01-05 10:46:53
【问题描述】:
我正在 Laravel 中构建一个多域/多商店电子商务应用程序,并希望在用户从商店更改为商店时保持登录状态。
但据我所知,Laravel 的 Auth 服务将登录用户保存在会话中,其他域无法访问会话。
有没有办法(可能是一个包)来实现这一点,而不会让我的应用程序容易出现可能的安全问题?
提前致谢!
【问题讨论】:
标签: session authentication laravel cross-domain
我正在 Laravel 中构建一个多域/多商店电子商务应用程序,并希望在用户从商店更改为商店时保持登录状态。
但据我所知,Laravel 的 Auth 服务将登录用户保存在会话中,其他域无法访问会话。
有没有办法(可能是一个包)来实现这一点,而不会让我的应用程序容易出现可能的安全问题?
提前致谢!
【问题讨论】:
标签: session authentication laravel cross-domain
我也在开发类似的单点登录系统,仍在努力寻找解决方案,但这是一个开始http://laravel.io/forum/03-14-2014-multiple-domains-how-to-share-login
在 laravel 上,您可以将 /app/config/session.php 驱动程序更改为 cookie
编辑:
这就是我所做的。
您可以使用像素图像跨域共享 cookie。 例如,当您登录 domain1.com 时,您想在 domain2.com 上创建一个 cookie,在登录 domain1.com 后,您需要拥有类似的东西
<img src="http://www.domain2.com/create-cookie?param=hash">
在 domain2.com 上面的路由:
【讨论】:
您可以手动设置会话 cookie 将注册的域,从而让它们在不同的站点上持续存在。只需在以下部分编辑config/session.php:
<?php
/*
|--------------------------------------------------------------------------
| Session Cookie Domain
|--------------------------------------------------------------------------
|
| Here you may change the domain of the cookie used to identify a session
| in your application. This will determine which domains the cookie is
| available to in your application. A sensible default has been set.
|
*/
'domain' => null,
?>
不过,您仍然仅限于一个顶级域。所以你可以有store1.shops.com 和store2.shops.com 共享会话,但不能有myshop.com 和shopsmart.com。
如果您需要这种格式的东西,您可能会通过创建身份验证服务并使用访问令牌来验证凭据来获得更好的效果。你也可以看看OneLogin之类的服务。
【讨论】:
Session::getId()
$sessionid_from_domainA = $_POST['session_from_A']
Session::setId($sessionid_from_domainA)
Session::start() 中启动会话
【讨论】:
在域 A 上创建一个像这样的图像<img src="https://DOMAINB.com/setcookie?id={{ Session::getId() }}" style="display:none;" />
在域 B 上创建一个路由,如下所示:
.
Route::get('setcookie', function(){
Session::setId($_GET['id']);
Session::start();
return 'Cookie created';
});`
$user = Auth::User; 获取您的用户了
【讨论】:
Session::setId(Crypt::decrypt($_GET['id'])); 另外,我在 IE9 及以下版本中遇到了问题。他们需要设置 P3P 标头,以便为其他域正确设置 cookie。所以我在 Session::start() 下方添加了这一行:header('P3P: CP="This is not a policy"'); 您可以在this post 中阅读有关 P3P 标头的更多信息。
如果你想在多个子域之间共享会话,那么你必须设置域名 config/session.php 已经设置了域名。
示例:如果你有 new.example.com 和 test.example.com 那么你必须将域名设置为 example.com
'domain' => env('SESSION_DOMAIN_URL','.example.com')
那里的解决方案对我有用,特别是设置域,然后清除我的浏览器 cookie 和缓存。
【讨论】:
我知道这并不完全符合我们的要求,但出于开发和测试目的,我这样做了:
在 config/session.php 中,尝试更改这一行
'path' => '/',
进入这个
'path' => '/;SameSite=None; secure',
允许我从不同的域进行身份验证。
现在,您应该能够编写一个简单的中间件来阻止不需要的主机。像这样。
namespace App\Http\Middleware;
use Illuminate\Http\Request;
use Closure;
class TrustedHosts{
public function handle($request, Closure $next){
//$host = $request->getHost();
$host = $request->headers->get('origin');
$enviroment = env('APP_ENV');
if ( $enviroment == 'development' ) {
$trustedHosts = array('localhost', 'dev.mydomain.com');
}
else {
$trustedHosts = array('anotherdomain.com', 'mydomain.com');
}
$isHostTrusted = in_array($host, $trustedHosts);
if ( !$isHostTrusted ) return response("I'm a teapot", 418); //Or any other code and message that you prefer.
return $next($request);
}
}
并将其分组到包含会话内容的中间件组中。
【讨论】:
基于Chirag Prajapati 的这个答案。你可以在 env 条目中使用$_SERVER['HTTP_HOST']:
来自/config/session.php
'domain' => env('SESSION_DOMAIN', $_SERVER['HTTP_HOST']),
然后从应用程序根目录:php artisan config:clear 并且不要关注警告消息,只需确保最后您已收到Configuration cache cleared! 这样您的应用程序会话将在您拥有的任何域上正常工作。
【讨论】: