Laravel API 身份验证(Passport),从后应用程序/json 中获取用户 ID
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/49414348/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Laravel API Authentication (Passport), Get user ID from a post application/json
提问by LKirin
My client is send a post application/json that has a accessToken in the json file. How do I verify the user and get the user id?
我的客户端发送一个 post application/json,在 json 文件中有一个 accessToken。如何验证用户并获取用户 ID?
Here is my api.php file:
这是我的 api.php 文件:
<?php
use Illuminate\Http\Request;
/* API Routes */
Route::get('/user', function (Request $request) {
return $request->user();
})->middleware('auth:api');
Route::post('/client', function (Request $request) {
$data = $request->json()->all();
return $data;
})->middleware('auth:api');
In the $data array i can see the accessToken.
在 $data 数组中,我可以看到 accessToken。
[user] => Array
(
[accessToken] => iOiJSUzI1NiIsImp0aSI6I...
)
It send back HTTP 401 : Unauthorized
它发回 HTTP 401 : Unauthorized
Any help would be great. Thanks
任何帮助都会很棒。谢谢
回答by Gonzalo
Is your client able to send the access token in the header?
您的客户端是否能够在标头中发送访问令牌?
Authorization: Bearer <token>
If so, you can use the auth:api
that you already have in your code, here you can see how to call it with an example using Guzzle:
https://laravel.com/docs/5.6/passport#protecting-routes
如果是这样,您可以使用auth:api
您的代码中已有的,在这里您可以通过使用 Guzzle 的示例了解如何调用它:https://laravel.com/docs/5.6/passport#protecting-routes
$response = $client->request('GET', '/api/user', [
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer '.$accessToken,
],
]);
Otherwise, and against my advice because it's more standard and secure to use the heather Authorization, you may have two (not very appropriate) alternatives:
否则,与我的建议相反,因为使用 heather 授权更加标准和安全,您可能有两个(不是很合适的)替代方案:
- You can create a middleware to check if there is no Authorization in the heather, but in the body, and if so, move it to the heather before the
auth:api
middleware (but be sure to run this middleware first). - Remove the
auth:api
middleware and authenticate either creating your own middleware or in the controller itself.
- 可以创建一个中间件来检查是否在heather中没有Authorization,而是在body中,如果有,则将其移动到
auth:api
中间件之前的heater中(但一定要先运行这个中间件)。 - 删除
auth:api
中间件并验证创建您自己的中间件或控制器本身。
Documentation about Laravel's middleware: https://laravel.com/docs/5.6/middleware
Laravel 中间件文档:https://laravel.com/docs/5.6/middleware
Here you can find more info about Laravel's out of the box authentication: https://laravel.com/docs/5.6/authentication
在这里您可以找到有关 Laravel 开箱即用身份验证的更多信息:https://laravel.com/docs/5.6/authentication
Note: Be sure that the documentation version and your Laravel's version match.
注意:确保文档版本和你的 Laravel 版本匹配。
More info about Barer Authentication: https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication
更多关于 Barer Authentication 的信息:https: //developer.mozilla.org/en-US/docs/Web/HTTP/Authentication
This is an example (not tested) of how the middleware could work:
这是中间件如何工作的示例(未测试):
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class BodyAuthenticate
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $guard
*
* @return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (!Auth::guard($guard)->check()
&& null !== ($token = $request->json('access.user.accessToken', null))) {
$request->headers->add([
'Authorization' => 'Bearer ' . $token,
]);
}
return $next($request);
}
}
You can also have a look at the Passport Middleware code here:
您还可以在此处查看 Passport Middleware 代码:
https://github.com/laravel/passport/blob/5.0/src/Http/Middleware/CreateFreshApiToken.php
https://github.com/laravel/passport/blob/5.0/src/Http/Middleware/CreateFreshApiToken.php
You have different ways to register your middleware:
您有不同的方式来注册您的中间件:
https://laravel.com/docs/5.6/middleware#registering-middleware
https://laravel.com/docs/5.6/middleware#registering-middleware
So you have to edit this file:
所以你必须编辑这个文件:
https://github.com/laravel/laravel/blob/master/app/Http/Kernel.php
https://github.com/laravel/laravel/blob/master/app/Http/Kernel.php
Depending on your API needs, you may do something like:
根据您的 API 需求,您可以执行以下操作:
protected $routeMiddleware = [
...
'auth.body' => \App\Http\Middleware\BodyAuthenticate::class,
];
And then you can add this middleware in your route:
然后你可以在你的路由中添加这个中间件:
Route::post('/client', function (Request $request) {
$data = $request->json()->all();
return $data;
})->middleware('auth.body', 'auth:api');
Or make something more global (if all API calls require token auth) adding the middlewares to the api middleware group (in within App\Http\Kernel
Class too):
或者做一些更全局的事情(如果所有 API 调用都需要令牌认证)将中间件添加到 api 中间件组(也在App\Http\Kernel
Class 中):
'api' => [
'throttle:60,1',
'bindings',
'auth.body',
'auth:api',
],
Then, if the token sent match with any token in your database, the auth singleton will return the user who owns it. You can get that user like:
然后,如果发送的令牌与数据库中的任何令牌匹配,则身份验证单例将返回拥有它的用户。你可以让那个用户喜欢:
https://laravel.com/docs/5.6/authentication#retrieving-the-authenticated-user
https://laravel.com/docs/5.6/authentication#retrieving-the-authenticated-user
use Illuminate\Support\Facades\Auth;
// Get the currently authenticated user...
$user = Auth::user();
// Get the currently authenticated user's ID...
$id = Auth::id();
Keep in mind that the client has to send the token in every single call (is not a session).
请记住,客户端必须在每次调用(不是会话)中发送令牌。
So you can protect the routes:
所以你可以保护路由:
- As the doc suggest (in the route or the controller):
- 正如文档所建议的(在路由或控制器中):
https://laravel.com/docs/5.6/authentication#protecting-routes
https://laravel.com/docs/5.6/authentication#protecting-routes
Route::get('client', function () {
// Only authenticated users may enter...
})->middleware('auth.body', 'auth:api');
Or in the controller:
或者在控制器中:
public function __construct()
{
$this->middleware('auth.body', 'auth:api');
}
- With a group route:
- 使用团体路线:
Route::middleware(['auth.body', 'auth:api'])->group(function () {
Route::get('client', function () {
// Uses first & second Middleware
});
Route::post('client', function (Request $request) {
// Uses first & second Middleware
$data = $request->json()->all();
return $data;
});
Route::get('client/user/profile', function () {
// Uses first & second Middleware
});
});
- If you edited
App\Http\Kernel
to add the middlewares globally (you don't need a group):
- 如果您编辑
App\Http\Kernel
以全局添加中间件(您不需要组):
Route::get('client', function () {
// Uses first & second Middleware
});
Route::post('client', function (Request $request) {
// Uses first & second Middleware
$data = $request->json()->all();
return $data;
});
Route::get('client/user/profile', function () {
// Uses first & second Middleware
});
Tip: you can use the groups to add, not only middleware
but also other interesting parameters such as controllers namespace
, domain
, naming alias prefix with as
, or URI path
prefix.
提示:您可以使用组来添加,不仅middleware
还包括其他重要的参数,如控制器namespace
,domain
,命名别名为前缀as
或URIpath
前缀。
Example:
例子:
Route::group([
'namespace' => 'Client', // Loads from App\Http\Controllers\Client
'domain' => 'client.domain.com',
'as' => 'client::', // Check with `php artisan route:list --name=client`
'middleware' => ['auth.body', 'auth:api'],
'prefix' => 'api',
], function () {
// Uses first & second Middleware
// GET https://client.domain.com/api/
Route::get('/', function () {
// ...
});
// Uses first & second Middleware
// GET https://client.domain.com/api/profile
Route::get('client/profile', function () {
$user = Auth::user();
// ...
});
// Uses first & second Middleware
// POST https://client.domain.com/api/profile
Route::post('client/profile', function (Request $request) {
// ...
});
// Uses first & second Middleware
// App\Http\Controllers\Client\PhotoController
// @link: https://laravel.com/docs/5.6/controllers#resource-controllers
// GET /photos index photos.index
// GET /photos/create create photos.create
// POST /photos store photos.store
// GET /photos/{photo} show photos.show
// GET /photos/{photo}/edit edit photos.edit
// PUT/PATCH /photos/{photo} update photos.update
// DELETE /photos/{photo} destroy photos.destroy
Route::resource('photos', 'PhotoController');
//...
});
Notice that, if you edited App\Http\Kernel
to add the middlewares globally, you don't need the middleware
in the group array.
请注意,如果您编辑App\Http\Kernel
以全局添加中间件,则不需要middleware
group 数组中的 。
回答by LKirin
Thanks To Gonxalo and fwartner See:https://laracasts.com/discuss/channels/laravel/laravel-53-with-passport-get-current-user-with-personal-access-token
感谢 Gonxalo 和 fwartner 参见:https://laracasts.com/discuss/channels/laravel/laravel-53-with-passport-get-current-user-with-personal-access-token
If the Access Token is Not in your header then do what Gonxalo says above.
如果访问令牌不在您的标题中,则按照 Gonxalo 上面所说的进行操作。
Then add fwartner suggestion to get your user id.
然后添加 fwartner 建议以获取您的用户 ID。
The Alexa Skill doesn't send the accessToken in the header it send it in the body. I hope this helps someone down the road.
Alexa 技能不会在标题中发送 accessToken,而是在正文中发送它。我希望这可以帮助某人。
Here is my api.php:
这是我的 api.php:
<?php
use Illuminate\Http\Request;
/*
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::get('/user', function (Request $request) {
return $request->user();
})->middleware('auth:api');
Route::post('/alexa', function (Request $request) {
$data = $request->json()->all();
$jsonArray = json_decode(json_encode($data),true);
$user = auth()->guard('api')->user();
$userid =$user->id;
$JsonOut = GetJsonResponse();
return $JsonOut;
})->middleware('auth.body', 'auth:api');
function GetJsonResponse(){
$NextNumber = 1;
$EndSession = "true";
$SpeakPhrase = "Alexa Success.";
$ReturnValue= '
{
"version": "1.0",
"sessionAttributes": {
"countActionList": {
"read": true,
"category": true,
"currentTask": "none",
"currentStep": '.$NextNumber.'
}
},
"response": {
"outputSpeech": {
"type": "PlainText",
"text": "' . $SpeakPhrase . '"
},
"reprompt": {
"outputSpeech": {
"type": "PlainText",
"text": "Say next item to continue."
}
},
"shouldEndSession": ' . $EndSession . '
}
}';
return $ReturnValue;
}
Also, I added a header to the BodyAuthenticate.php middleware
另外,我在 BodyAuthenticate.php 中间件中添加了一个标头
$request->headers->add(['Accept' => 'application/json' ]); $request->headers->add(['Authorization' => 'Bearer ' . $token, ]);
$request->headers->add(['Accept' => 'application/json' ]); $request->headers->add(['Authorization' => 'Bearer' . $token, ]);