如何在 Laravel 应用程序中获取客户端 ID?
How do I get the client id in a Laravel app?
我已经设置了一个带有客户端身份验证的 laravel 应用程序。我将我的客户 ID 和客户密码发送给它,它给了我一个令牌。我可以登录我的 laravel 应用程序,但我不知道如何获取已授权客户端的 ID。
我看到了使用 auth()->user()->Token()->getAttribute('client_id')
获取客户端 ID 的提示,但由于我只使用客户端,因此没有用户,我收到关于尝试调用 Token() 为 null 的错误object。 Auth::id()
也没有返回任何内容。我用 Request::header('Authorization')
从 header 中获取了令牌,但它与数据库中的任何内容都不匹配。
我假设您正在使用客户端凭据授予令牌和 CheckClientCredentials
中间件。
您可以从不记名令牌中获取此信息,但这并不是那么简单。您需要使用令牌创建一个新的 PSR7 请求,并将其发送到 oauth 服务器以将其转换为可读数据。
这已经在 Passport 提供的 CheckClientCredentials
中间件中完成。因此,一种方法是扩展 CheckClientCredentials
中间件,然后从中间件内部手动设置请求对象上所需的字段。
首先,创建app/Http/Middleware/MyCheckClientCredentials.php
:
namespace App\Http\Middleware;
use Closure;
use Illuminate\Auth\AuthenticationException;
use League\OAuth2\Server\Exception\OAuthServerException;
use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory;
use Laravel\Passport\Http\Middleware\CheckClientCredentials;
class MyCheckClientCredentials extends CheckClientCredentials
{
/**
* The Resource Server instance.
*
* @var \League\OAuth2\Server\ResourceServer
*/
private $server;
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param mixed ...$scopes
* @return mixed
* @throws \Illuminate\Auth\AuthenticationException
*/
public function handle($request, Closure $next, ...$scopes)
{
$psr = (new DiactorosFactory)->createRequest($request);
try {
$psr = $this->server->validateAuthenticatedRequest($psr);
// This is the custom line. Set an "oauth_client_id" field on the
// request with the client id determined by the bearer token.
$request['oauth_client_id'] = $psr->getAttribute('oauth_client_id');
} catch (OAuthServerException $e) {
throw new AuthenticationException;
}
$this->validateScopes($psr, $scopes);
return $next($request);
}
}
接下来,更新您的 app/Http/Kernel.php
以使用您的自定义中间件而不是 Passport 中间件中的构建:
protected $routeMiddleware = [
'client' => \App\Http\Middleware\MyCheckClientCredentials::class,
];
像往常一样将中间件应用到您的路由:
Route::get('/user', function(Request $request) {
// Should show "oauth_client_id" field.
dd($request->all());
})->middleware('client');
如果您不想在中间件内部执行此操作,您可以研究 Passport 中间件的工作原理,如果愿意,可以在某种类型的服务中重用此代码。
注意:全部未经测试。
我不得不在我的记录器中间件中做类似的事情:
.......................
$user = $request->user();
if($user) {
// assume the authorization header exists, since the user is authenticated
$header = $request->headers->get('authorization');
if($header) { // authorization header is not set when testing via Passport::actingAs()
/**
* Stolen from League\OAuth2\Server\AuthorizationValidators\BearerTokenValidator#63
*/
// Get the actual jwt string from the header
$jwt = trim(preg_replace('/^(?:\s+)?Bearer\s/', '', $header));
// Parse the token from the string
$token = (new Lcobucci\JWT\Parser())->parse($jwt);
// Get the ID from the token
$oauthClientId = $token->getClaim('aud');
}
}
.......................
我已经设置了一个带有客户端身份验证的 laravel 应用程序。我将我的客户 ID 和客户密码发送给它,它给了我一个令牌。我可以登录我的 laravel 应用程序,但我不知道如何获取已授权客户端的 ID。
我看到了使用 auth()->user()->Token()->getAttribute('client_id')
获取客户端 ID 的提示,但由于我只使用客户端,因此没有用户,我收到关于尝试调用 Token() 为 null 的错误object。 Auth::id()
也没有返回任何内容。我用 Request::header('Authorization')
从 header 中获取了令牌,但它与数据库中的任何内容都不匹配。
我假设您正在使用客户端凭据授予令牌和 CheckClientCredentials
中间件。
您可以从不记名令牌中获取此信息,但这并不是那么简单。您需要使用令牌创建一个新的 PSR7 请求,并将其发送到 oauth 服务器以将其转换为可读数据。
这已经在 Passport 提供的 CheckClientCredentials
中间件中完成。因此,一种方法是扩展 CheckClientCredentials
中间件,然后从中间件内部手动设置请求对象上所需的字段。
首先,创建app/Http/Middleware/MyCheckClientCredentials.php
:
namespace App\Http\Middleware;
use Closure;
use Illuminate\Auth\AuthenticationException;
use League\OAuth2\Server\Exception\OAuthServerException;
use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory;
use Laravel\Passport\Http\Middleware\CheckClientCredentials;
class MyCheckClientCredentials extends CheckClientCredentials
{
/**
* The Resource Server instance.
*
* @var \League\OAuth2\Server\ResourceServer
*/
private $server;
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param mixed ...$scopes
* @return mixed
* @throws \Illuminate\Auth\AuthenticationException
*/
public function handle($request, Closure $next, ...$scopes)
{
$psr = (new DiactorosFactory)->createRequest($request);
try {
$psr = $this->server->validateAuthenticatedRequest($psr);
// This is the custom line. Set an "oauth_client_id" field on the
// request with the client id determined by the bearer token.
$request['oauth_client_id'] = $psr->getAttribute('oauth_client_id');
} catch (OAuthServerException $e) {
throw new AuthenticationException;
}
$this->validateScopes($psr, $scopes);
return $next($request);
}
}
接下来,更新您的 app/Http/Kernel.php
以使用您的自定义中间件而不是 Passport 中间件中的构建:
protected $routeMiddleware = [
'client' => \App\Http\Middleware\MyCheckClientCredentials::class,
];
像往常一样将中间件应用到您的路由:
Route::get('/user', function(Request $request) {
// Should show "oauth_client_id" field.
dd($request->all());
})->middleware('client');
如果您不想在中间件内部执行此操作,您可以研究 Passport 中间件的工作原理,如果愿意,可以在某种类型的服务中重用此代码。
注意:全部未经测试。
我不得不在我的记录器中间件中做类似的事情:
.......................
$user = $request->user();
if($user) {
// assume the authorization header exists, since the user is authenticated
$header = $request->headers->get('authorization');
if($header) { // authorization header is not set when testing via Passport::actingAs()
/**
* Stolen from League\OAuth2\Server\AuthorizationValidators\BearerTokenValidator#63
*/
// Get the actual jwt string from the header
$jwt = trim(preg_replace('/^(?:\s+)?Bearer\s/', '', $header));
// Parse the token from the string
$token = (new Lcobucci\JWT\Parser())->parse($jwt);
// Get the ID from the token
$oauthClientId = $token->getClaim('aud');
}
}
.......................