研究的原因 :因为我们多有的项目都是前后端分离所以会存在多个api 项目我用的是5.5版本所有直接用来自带的passport下载我就不说了直接说思路 放代码
api是自己就有的 现在我们需要一个 admin的项目
在auth.php guards 进行管理的
下面对应好你上面的认证数据库
AdminUser这个模型自己建跟User大同小异制定好表名就好
然后我们就写登录返回token
然后就是一个公共的 Traits 放在哪里看自己喜好 我只提供代码 PASSWORD_ID PASSWORD_SECRET 这两个是根据文档生成的在这里我就不说了 验证的范围也是自己修改的 不一定是*
<?php
namespace App\Http\Controllers\Common\Traits;
use GuzzleHttp\Client;
trait ProxyTrait
{
/**
* 陌生刘:?
* Notes:刷新令牌
* User: lyc
* Date: 2019/7/12
* Time: 17:41
* @param $refreshToken
* @return mixed|\Psr\Http\Message\ResponseInterface
*/
public function getRefresh ($refreshToken, $provider = '')
{
$data = [
'grant_type' => 'refresh_token',
'refresh_token' => $refreshToken,
'client_id' => env('PASSWORD_ID'),
'client_secret' => env('PASSWORD_SECRET'),
'scope' => '*',
];
empty($provider) ? '' : $data['provider'] = $provider;
return $this->token($data);
}
/**
* 陌生刘:?
* Notes:登录返回token
* User: lyc
* Date: 2019/7/12
* Time: 17:41
* @param $username
* @param $password
* @param $provider
* @return mixed|\Psr\Http\Message\ResponseInterface
*/
protected function getProxy ($username, $password, $provider = '')
{
$data = [
'grant_type' => 'password',
'client_id' => env('PASSWORD_ID'),
'client_secret' => env('PASSWORD_SECRET'),
'username' => $username,
'password' => $password,
'scope' => '*',
];
empty($provider) ? '' : $data['provider'] = $provider;
return $this->token($data);
}
/**
* 陌生刘:?
* Notes:获取token
* User: lyc
* Date: 2019/7/12
* Time: 17:40
* @param array $data
* @return mixed|\Psr\Http\Message\ResponseInterface
*/
protected function token ($data = [])
{
$http = new Client();
$url = \request()->root() . '/oauth/token';
$result = $http->post($url, [
'form_params' => $data
]);
$result = json_decode((string)$result->getBody(), true);
return $result;
}
/**
* 陌生刘:?
* Notes:客户端凭据授权令牌
* User: lyc
* Date: 2019/7/12
* Time: 17:40
* @param $provider
* @return mixed
*/
public function client ($provider = '')
{
$http = new Client();
$url = \request()->root() . '/oauth/token';
$data = [
'form_params' => [
'grant_type' => 'client_credentials',
'client_id' => env('PASSWORD_ID'),
'client_secret' => env('PASSWORD_SECRET'),
'scope' => '*',
]
];
empty($provider) ? '' : $data['provider'] = $provider;
$response = $http->post($url, $data);
$result = json_decode((string)$response->getBody(), true);
return $result;
}
}
然后前面的已经可以了但是还不能多表
<?php
/**
* 陌生刘:?
* Created by PhpStorm.
* User: StubbornGrass - liu
* Date: 2019/7/12
* Time: 10:38
*/
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Config;
class PassportCustomProvider
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle ($request, Closure $next)
{
$params = $request->all();
if ( !empty($params['provider']) ) {
Config::set('auth.guards.api.provider', $params['provider']); // 动态配置 auth.guards.api.provider 的 model
}
return $next($request);
}
}
这里需要写这一个中间件 来修改我们验证的模型这一步的意义在于
源码里面是直接获取的api 下面的模型不支持多表认证 一开始我觉着自己重写一下这里就可以了但是发现会出现两个表相同的UserID 互相可以读取的数据的问题 这其实是一种思路我就直接换成下面的写法了
然后在这里注册 token相关的路由的时候 我们需要给他加一个中间键改变认认证的模型 从而正确的返回 token信息
但是这样用有一个问题就是admin 和User 同事都有用户id 为1 的时候他们之间的token就会互用造成登录一个端其他的端拿着token去访问可以进行下去 这样会非常危险所以我们需要增加一些东西
<?php
namespace App\Listeners;
use Carbon\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
class PassportAccessTokenCreated
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct ()
{
//
}
/**
* Handle the event.
*
* @param \Laravel\Passport\Events\AccessTokenCreated $event
* @return void
*/
public function handle (\Laravel\Passport\Events\AccessTokenCreated $event)
{
$provider = \Config::get('auth.guards.api.provider');
DB::table('oauth_access_token_providers')->insert([
"oauth_access_token_id" => $event->tokenId,
"provider" => $provider,
"created_at" => new Carbon(),
"updated_at" => new Carbon(),
]);
}
}
?>
通过一个平台与tokenid的 中间表关联起来
到了这里其实最关键的才出现因为上面有一个问题我也一直在说就是 多表同id 会出现互相可以读取数据的问题
然后这里再次加一个中间件
然后就可以跑起来了 配置好验证的中间件 就可以多平台多表多字段的登录验证了
退出时要删除表里的tokenid 或者把他失效都是可以的
刷新token 时我是带着刷新token过来验证看使用的人改成其他的也可以 在这里删除token 与平台的中间表里的数据
所有的就都可以的了 这里面那个用auth 来获取用户信息的其实不准确但是配合着路由中间件还是没问题 但是还是可以在进行一些优化的