背景
我有一个微服务设置,流程是:
client > api gateway > auth server > api gateway > microservice
微服务身份验证
我创建了一个JwtGuard,它可以解码JWT并使用GenericUser创建用户:
auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\User::class,
],
],
AuthServiceProvider.php
public function boot()
{
$this->registerPolicies();
Auth::extend('jwt', function ($app) {
return new JwtGuard($app['request']);
});
}
JwtGuard.php
<?php
namespace App\Services\Auth;
use Illuminate\Auth\GenericUser;
use Illuminate\Auth\GuardHelpers;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Guard;
use \Firebase\JWT\JWT;
use Illuminate\Http\Request;
class JwtGuard implements Guard {
use GuardHelpers;
/**
* @var Request
*/
private $request;
public function __construct(Request $request)
{
$this->request = $request;
}
/**
* Get the currently authenticated user.
*
* @return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function user()
{
if (!is_null($this->user)) {
return $this->user;
}
if(!$jwt = $this->getJwt()) {
return null;
}
return $this->decode($jwt);
}
/**
* Validate a user's credentials.
*
* @param array $credentials
* @return bool
*/
public function validate(array $credentials = [])
{
if(!$jwt = $this->getJwt()) {
return false;
}
return !is_null($this->decode($jwt))?true:false;
}
/**
* Decode JWT and return user
*
* @return mixed|null
*/
private function decode($jwt)
{
$publicKey = file_get_contents(storage_path('oauth-public.key'));
try {
$res = JWT::decode($jwt, $publicKey, array('RS256'));
return $this->user = new GenericUser(json_decode(json_encode($res->user), true));
} catch (\Exception $e) {
return null;
}
}
private function hasAuthHeader()
{
return $this->request->header('Authorization')?true:false;
}
private function getJwt()
{
if(!$this->hasAuthHeader()){
return null;
}
preg_match('/Bearer\s((.*)\.(.*)\.(.*))/', $this->request->header('Authorization'), $jwt);
return $jwt[1]?$jwt[1]:null;
}
}
问题
这可以正常工作,除了:
我到目前为止所拥有的
我尝试了以下方法来将本地用户数据与JWT配置文件合并:
private function decode($jwt)
{
$publicKey = file_get_contents(storage_path('oauth-public.key'));
try {
$res = JWT::decode($jwt, $publicKey, array('RS256'));
$this->user = new GenericUser(json_decode(json_encode($res->user), true));
$this->user->localUser = \App\User::where('user_id', $this->user->id)->first();
return $this->user;
} catch (\Exception $e) {
return null;
}
}
但是这仍然使GenericUser没有can()函数。
帮助...请!
我不禁感到有一种更好的(正确的)方法可以使用“用户”而不是“ GenericUser”来实现,这将允许Laravel中的所有身份验证/授权功能正常工作并合并数据
答案 0 :(得分:0)
我通过在用户构造中添加$ jwt_user来跳过“可填充”来解决此问题:
auth.php
'defaults' => [
'guard' => 'api',
],
'guards' => [
'api' => [
'driver' => 'jwt',
],
],
AuthServiceProvider.php
use App\User;
use \Firebase\JWT\JWT;
public function boot()
{
$this->registerPolicies();
Auth::viaRequest('jwt', function ($request) {
$publicKey = file_get_contents(storage_path('oauth-public.key'));
if(!$hasAuthHeader = $request->header('Authorization')?true:false){
return null;
}
preg_match('/Bearer\s((.*)\.(.*)\.(.*))/', $request->header('Authorization'), $jwt);
try {
$res = JWT::decode($jwt[1], $publicKey, array('RS256'));
$jwt_user = json_decode(json_encode($res->user), true);
$local_user = User::find($jwt_user['id']);
$jwt_user['local_profile'] = $local_user?$local_user:[];
$user = new User([], $jwt_user);
return $user;
} catch (\Exception $e) {
return null;
}
});
}
User.php
public function __construct(array $attributes = array(), $jwt_user = array())
{
parent::__construct($attributes);
foreach($jwt_user as $k=>$v){
$this->$k = $v;
}
}
答案 1 :(得分:0)
实现这一目标的简单方法是:
use Firebase\JWT\JWT;
use Laravel\Passport\Token;
$jwt = 'eyJ0...';
$publicKey = file_get_contents(storage_path('oauth-public.key'));
$res = JWT::decode($jwtToken, $publicKey, ['RS256']);
$user = Token::findOrFail($res->jti)->user;