Laravel8.x实现跨站登录
如有一个系统A,系统A下有很多子系统,共享用户信息,在子系统中登录了,其他系统不要再次进行登录。除了跨站登录外,还有单点登录也可以实现。今天学习的是跨站登录,记录一下。
第一步:创建两个项目,分别为主系统和子系统
# 主系统
composer create-project laravel/laravel demo.com
# 子系统
composer create-project laravel/laravel sub.demo.com
第二步:配置域名
# demo.com 主系统域名(顶级域名)
demo.com
# sub.demo.com 子系统域名(二级域名)
sub.demo.com
第三步:创建数据库并修改 .env
文件连接数据库
# demo.com 主系统数据库名
2021_demo
# sub.demo.com 子系统数据库名
2021_sub_demo
主系统和子系统分别在
.env
文件中配置对应的数据库
第四步:使用迁移文件生成数据表
# demo.com 主系统 && sub.demo.com
# 两个系统中都要执行这个命令
php artisan migrate
第五步:主系统和子系统引入脚手架
主系统和子系统都要执行如下操作
composer require laravel/ui
php artisan ui bootstrap --auth
npm install
npm run dev
安装完成后在浏览器中分别访问主系统demo.com
和子系统sub.demo.com
就能在右上角看到Log in
和Register
。
第六步:配置sub.demo.com子系统
1)配置sub.demo.com子系统数据库连接到主系统
// 位置:sub.demo.com 子系统
// config/database.php
'connections' => [
// 连接到主数据库
'demo_mysql' => [
'driver' => 'mysql',
'url' => env('DATABASE_URL'),
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', '3306'),
// 主数据库
'database' => '2021_demo',
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'prefix_indexes' => true,
'strict' => true,
'engine' => null,
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
]) : [],
],
]
我这里主系统与子系统的数据库账号、密码是一样的,因此只修改了数据库名。
2)子系统User模型类配置连接
// 位置:子系统
// sub.demo.com
// app/Models/User.php
// 子系统用户模型中新增如下两个配置
// 连接到主系统数据库,demo_mysql是在database.php配置文件中
// 配置连接到主系统的名字
protected $connection = 'demo_mysql';
// 使用的数据表
protected $table = 'users';
第七步:简单测试
1)浏览中访问主系统demo.com/register
并注册一个用户
2)sub.demo.com子系统中获取主系统注册的用户
// 位置:sub.demo.com 子系统
// routes/web.php
// 获取主系统中的用户
Route::get('sub', function(){
dd(\App\Models\User::all());
});
3)浏览器中访问子系统sub.demo.com/sub
,可以看到获取到了主系统的用户信息了。
4)查看两个系统数据库中的users表,发现只主系统的users表中有用户数据。
第八步:配置基于数据库的session共享驱动
1)主系统和子系统都执行如下操作
php artisan session:table
php artisan migrate
执行完后,会在数据库中生成一个
sessions
表,用于存储session信息
2)修改驱动为数据库驱动
// .env
// 主系统和子系统的驱动都设置为database
SESSION_DRIVER=database
3)分别访问demo.com
和sub.demo.com
# 主系统数据库
mysql> select * from 2021_demo.sessions\G;
*************************** 1. row ***************************
id: 0XBn9XXqJ6fA3yGO5Lx0IjkURT5PVbIawvezRphV
user_id: NULL
ip_address: 127.0.0.1
user_agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
payload: 省略该信息,太长了
last_activity: 1636888685
1 row in set (0.00 sec)
# 子系统数据库
mysql> select * from 2021_sub_demo.sessions\G;
*************************** 1. row ***************************
id: CZBCGqcAEEMWp3IUWh8LYKO8ROXcbgXwtde0f5Z0
user_id: NULL
ip_address: 127.0.0.1
user_agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
payload: 省略该信息,太长了
last_activity: 1636888738
1 row in set (0.00 sec)
可以看到user_id
为NULL,说明用户没有登录,用户登录后,user_id
将记录用户的ID。
4)配置session共享
// 位置:子系统
// config/session.php
// 将子系统连接主系统的session
'connection' => 'demo_mysql',
注意:此时,主系统中的sessions
表中只有一条记录。子系统中的seesion连接修改到主系统后,再次访问子系统sub.demo.com
生,就会发现,在主系统中的sessions表多出了一条session记录,这个记录就是子系统的session信息。
第九步:跨站登录的实现
1)修改主系统和子系统的session域名
// config/session.php
'domain' => '.demo.com',
主系统和子系统的domain值设置成一样。
2)将主系统中的APP_KEY
值覆盖子系统的APP_KEY
值。
// 主系统
// .env
APP_KEY=base64:788KCi6RQZH3/fTm5wr04CGFOdMR1Ht7GvHk7JL15WM=
// 子系统
// .env
APP_KEY=base64:788KCi6RQZH3/fTm5wr04CGFOdMR1Ht7GvHk7JL15WM=
3)删除主系统数据库sessions表中的数据
4)清除浏览器缓存,并访问主系统和子系统,将看到主系统数据库中sessions表中只有一条session记录。
第十步:跨站登录实现的测试
1)子系统中使用第七步
在主主系统中注册的用户进行登录。
访问:sub.demo.com/login
进行登录,子登录登录成功
2)访问主系统demo.com
,发现已经处于登录状态。
3)在主系统中退出,然后在访问子系统,发现子已经系统退出
4)在主系统中进行登录,然后刷新子系统,发现子系统已登录。