我正在使用Laravel Framework版本5.3.9,通过composer(除了"laravel/passport": "^1.0")没有添加任何新内容.
我做了文档中建议的所有事情.表已创建,路由已启动,一切正常.但是我需要API的护照.
我的路线看起来像这样:
+--------+----------+-----------------------------------------+----------------------+----------------------------------------------------------------------------+------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+----------+-----------------------------------------+----------------------+----------------------------------------------------------------------------+------------+
| | GET|HEAD | / | | Closure | web |
| | GET|HEAD | api/v1/users/register | api::users::register | App\Http\Controllers\Api\V1\SocialController@register | api,auth |
| | POST | oauth/authorize | | \Laravel\Passport\Http\Controllers\ApproveAuthorizationController@approve | web,auth |
| | GET|HEAD | oauth/authorize | | \Laravel\Passport\Http\Controllers\AuthorizationController@authorize | web,auth |
| | DELETE | oauth/authorize | | \Laravel\Passport\Http\Controllers\DenyAuthorizationController@deny | web,auth |
| | GET|HEAD | oauth/clients | | \Laravel\Passport\Http\Controllers\ClientController@forUser | web,auth |
| | POST | oauth/clients | | \Laravel\Passport\Http\Controllers\ClientController@store | web,auth |
| | PUT | oauth/clients/{client_id} | | \Laravel\Passport\Http\Controllers\ClientController@update | web,auth |
| | DELETE | oauth/clients/{client_id} | | \Laravel\Passport\Http\Controllers\ClientController@destroy | web,auth |
| | GET|HEAD | oauth/personal-access-tokens | | \Laravel\Passport\Http\Controllers\PersonalAccessTokenController@forUser | web,auth |
| | POST | oauth/personal-access-tokens | | \Laravel\Passport\Http\Controllers\PersonalAccessTokenController@store | web,auth |
| | DELETE | oauth/personal-access-tokens/{token_id} | | \Laravel\Passport\Http\Controllers\PersonalAccessTokenController@destroy | web,auth |
| | GET|HEAD | oauth/scopes | | \Laravel\Passport\Http\Controllers\ScopeController@all | web,auth |
| | POST | oauth/token | | \Laravel\Passport\Http\Controllers\AccessTokenController@issueToken | |
| | POST | oauth/token/refresh | | \Laravel\Passport\Http\Controllers\TransientTokenController@refresh | web,auth |
| | GET|HEAD | oauth/tokens | | \Laravel\Passport\Http\Controllers\AuthorizedAccessTokenController@forUser | web,auth |
| | DELETE | oauth/tokens/{token_id} | | \Laravel\Passport\Http\Controllers\AuthorizedAccessTokenController@destroy | web,auth |
+--------+----------+-----------------------------------------+----------------------+----------------------------------------------------------------------------+------------+
Run Code Online (Sandbox Code Playgroud)
所有的web路线都在那里,没有api相关的路线,因为Passport没有提供开箱即用的任何东西.
API本身旨在供受信任的客户端使用,它是为需要登录的移动应用程序而设计的,然而,所述登录将绕过几个步骤.
一旦用户访问该/register路线,注册过程本身就非常简单:访问用户的Facebook帐户,抓住几个字段 - 电子邮件,脸谱ID,命名个人资料图片,从那时起,用户被视为已注册.但用户不会登录facebook(这是一个非常重要的方面).消费者应用程序将被发出一个令牌并使用该令牌访问api的各个端点(需要使用令牌).
所以归结为这个.我需要向访问API的消费者应用程序发出访问令牌.API本身只有一个客户端,即移动应用程序本身.使用该应用程序的用户不被视为API的客户端,而是移动应用程序本身的客户端.
到目前为止,在实现API相关的东西时,Passport是一个令人头痛的问题,或者我无法弄清楚如何让它正常工作.
我在oauth_clients表中创建了一个看起来像这样的测试客户端:
我正在使用Postman访问api/v1/users/register具有以下auth中间件的路由JSON application/json
{
"grant_type" : "authorization_code",
"client_id" : 5,
"client_secet": "y5dvPIOxQJOjYn7w2zzg4c6TRrphsrNFWbG4gAUL"
}
Run Code Online (Sandbox Code Playgroud)
这当然会导致一个
{"error":"Unauthenticated."}
Run Code Online (Sandbox Code Playgroud)
这很有道理.出于纯粹的好奇心,我改变了这/register条路线:
Route::group([
'middleware' => [
],
], function ()
{
Route::group([
'prefix' => 'users',
'as' => 'users::',
], function ()
{
// Route::get('/register', ['as' => 'register', 'uses' => 'Api\V1\SocialController@register',]);
Route::post('/register', ['as' => 'register', 'uses' => '\Laravel\Passport\Http\Controllers\AccessTokenController@issueToken',]);
});
});
Run Code Online (Sandbox Code Playgroud)
跟json以前一样.结果导致了{"error":"invalid_client","message":"Client authentication failed"}.
我已经找到了,我认为,处理功能validateClient部分vendor/league的oauth2服务器/ src目录/格兰特/ AbstractGrant`.
该$client为空.现在这可能与Passport有关,也可能没有关系,因为它上面的文档相当缺乏,并想通过一个包的怪物来挖掘错误,这可能主要是由于我没有做正确的事情,这并没有让我受伤作为一个好主意,我没有选择.说实话,我甚至不知道问题是什么.
真的,在这一点上任何指向正确方向的东西都非常受欢迎.
问题的部分是
Shu*_*med 21
Laravel 5.3护照的问题在于,与之前由lucadegasperi提供的Laravel库的OAuth 2.0服务器不同,它没有直接创建客户端的API.因此,现在客户端只能通过前端进行.仅供参考我们希望仅为我们的移动应用程序使用laravel护照,因此在创建和注册用户时,我们只有EMAIL和密码,在某些情况下只有Facebook用户ID才能登录.因此,以下方法对我们的情况非常有效,并且可能因您的情况而有所不同,但可能会帮助您从长远来看使用laravel护照.
注意:在遵循以下内容之前,假设您已在应用程序中启用了密码授予.
所以我们为laravel 5.3项目解决它的方式如下:
在oauth_clients中将id字段转换为普通字段,即将其作为主键删除,并将数据类型设置为varchar,以便我们可以将电子邮件地址存储为client_ids,因为它们对于您的系统也是唯一的.在Facebook登录的情况下,我们将Facebook用户ID存储在此列中,这对于我们的每个客户来说也是唯一的.对于其他表,例如:oauth_access_tokens,oauth_auth_codes和oauth_personal_access_clients将client_id更改为VARCHAR(255),以便它可以存储电子邮件地址或Facebook用户ID.
现在转到模型并为oauth_clients表创建模型,以便您可以在创建用户时以编程方式从代码创建客户端.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class OauthClient extends Model
{
protected $table = 'oauth_clients';
}
Run Code Online (Sandbox Code Playgroud)然后在api.php路由文件中添加以下路由:
Route::post('/register-user', function (Request $request) {
$name = $request->input('name');
$email = $request->input('email'),
$password = $request->input('password'),
// save new user
$user = \App\User::create([
'name' => $name,
'email' => $email,
'password' => bcrypt($password),
]);
// create oauth client
$oauth_client = \App\OauthClient::create([
'user_id' => $user->id,
'id' => $email,
'name' => $name,
'secret' => base64_encode(hash_hmac('sha256',$password, 'secret', true)),
'password_client' => 1,
'personal_access_client' => 0,
'redirect' => '',
'revoked' => 0,
]);
return [
'message' => 'user successfully created.'
];
});
Run Code Online (Sandbox Code Playgroud)在上面的代码片段中,您必须注意,要生成oauth_client秘密,您必须使用一些强大的加密公式,您觉得将其与您的应用程序一起使用是很舒服的.此外,使用相同的技术在您的移动应用程序上为相应的客户端/用户生成密钥.
现在,您可以使用laravel passport提供的标准POST API,使用以下参数使用"oauth/token"通过密码授权请求访问令牌:
grant_type : 'password'
client_id : '<email with which the user is registered>'
client_secret : '<generate the client secret from the mobile app>'
username : '<email with which the user is registered>'
password : '<password entered by the user>'
scope : '<leave empty as default>'
Run Code Online (Sandbox Code Playgroud)如果一切正确,上面会给你一个回应,类似于:
{
"token_type": "Bearer",
"expires_in": 3155673600,
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjMwZmM0MDk1NWY5YjUwNDViOTUzNDlmZjc2M2ExNDUxOTAxZjc5YTA5YjE4OWM1MjEzOTJlZmNiMDgwOWQzMzQwM2ExZWI4ZmMyODQ1MTE3In0.eyJhdWQiOiJzaHVqYWhtQGdtYWlsLmNvbSIsImp0aSI6IjMwZmM0MDk1NWY5YjUwNDViOTUzNDlmZjc2M2ExNDUxOTAxZjc5YTA5YjE4OWM1MjEzOTJlZmNiMDgwOWQzMzQwM2ExZWI4ZmMyODQ1MTE3IiwiaWF0IjoxNDc4MTQ1NjMyLCJuYmYiOjE0NzgxNDU2MzIsImV4cCI6NDYzMzgxOTIzMiwic3ViIjoiMSIsInNjb3BlcyI6W119.dj3g9b2AdPCK-im5uab-01SP71S7AR96R0FQTKKoaZV7M5ID1pSXDlmZw96o5Bd_Xsy0nUqFsPNRQsLvYaOuHZsP8v9mOVirBXLIBvPcBc6lDRdNXvRidNqeh4JHhJu9a5VzNlJPm3joBYSco4wYzNHs2BPSxXuuD3o63nKRHhuUHB-HwjVxj2GDwzEYXdZmf2ZXOGRJ99DlWGDvWx8xQgMQtd1E9Xk_Rs6Iu8tycjBpKBaC24AKxMI6T8DpelnFmUbMcz-pRsgCWCF_hxv6FpXav3jr1CLhhT58_udBvXjQAXEbtHeB7W_oaMcaqezHdAeOWDcnqREZHsnXHtKt0JpymcTWBkS2cg7sJzy6P9mOGgQ8B4gb8wt44_kHTeWnokk4yPFRZojkHLVZb8YL6hZxLlzgV1jCHUxXoHNe1VKlHArdlV8LAts9pqARZkyBRfwQ8oiTL-2m16FQ_qGg-9vI0Suv7d6_W126afI3LxqDBi8AyqpQzZX1FWmuJLV0QiNM0nzTyokzz7w1ilJP2PxIeUzMRlVaJyA395zq2HjbFEenCkd7bAmTGrgEkyWM6XEq1P7qIC_Ne_pLNAV6DLXUpg9bUWEHhHPXIDYKHS-c3N9fPDt8UVvGI8n0rPMieTN92NsYZ_6OqLNpcm6TrhMNZ9eg5EC0IPySrrv62jE",
"refresh_token": "BbwRuDnVfm7tRQk7qSYByFbQKK+shYPDinYA9+q5c/ovIE1xETyWitvq6PU8AHnI5FWb06Nl2BVoBwCHCUmFaeRXQQgYY/i5vIDEQ/TJYFLVPRHDc7CKILF0kMakWKDk7wJdl5J6k5mN38th4pAAZOubiRoZ+2npLC7OSZd5Mq8LCBayzqtyy/QA5MY9ywCgb1PErzrGQhzB3mNhKj7U51ZnYT3nS5nCH7iJkCjaKvd/Hwsx2M6pXnpY45xlDVeTOjZxxaOF/e0+VT2FP2+TZMDRfrSMLBEkpbyX0M/VxunriRJPXTUvl3PW0sVOEa3J7+fbce0XWAKz7PNs3+hcdzD2Av2VHYF7/bJwcDCO77ky0G4JlHjqC0HnnGP2UWI5qR+tCSBga7+M1P3ESjcTCV6G6H+7f8SOSv9FECcJ8J5WUrU+EHrZ95bDtPc9scE4P3OEQaYchlC9GHk2ZoGo5oMJI6YACuRfbGQJNBjdjxvLIrAMrB6DNGDMbH6UZodkpZgQjGVuoCWgFEfLqegHbp34CjwL5ZFJGohV+E87KxedXE6aEseywyjmGLGZwAekjsjNwuxqD2QMb05sg9VkiUPMsvn45K9iCLS5clEKOTwkd+JuWw2IU80pA24aXN64RvOJX5VKMN6CPluJVLdjHeFL55SB7nlDjp15WhoMU1A="
}
Run Code Online (Sandbox Code Playgroud)它只是一个临时解决方案,直到laravel为只有移动设备作为创建oAuth客户端和用户的唯一可能接口的应用程序支持外部API.
希望它能帮到你!干杯.
And*_* F. 10
因为标记的答案被认为是正确的,所以我觉得有必要注意一些我认为会同意的关键点:
你几乎从来没有想要把你的路由目录中的那种服务器进程逻辑.特别是在创建一个旨在将其投入生产的API时.这是一条肮脏的路线,并不完全安全. 除非是在您的路径目录中可以安全处理的事情.比如,在较小的范围内,用于向工作人员发送关于作为示例发布的新信件/博客/备忘录的通知(SMS,电子邮件,推送,松弛)的基本逻辑.
在尝试"hackishly"完成之前可能已完成多次的任务之前,始终尝试利用并尽可能多地利用框架的功能.
确保您正在对已经完成的事情进行适当的研究.这样,它可以更容易地简单地引用一个视频或教程,显示如何正确地做某人正在尝试做的事情.
话虽如此,一个很好的起点是观看以下视频,该视频完美地描述了如何正确设置您要设置的内容的基础知识:
https://laracasts.com/series/whats-new-in-laravel-5-3/episodes/13
在许多方面,视频教程从头到尾都做得非常好,彻底.请务必仔细查看OAuth2.0的不同Grant_Types,以便根据应用程序使用api的位置更好地了解您/您的应用程序需要的特定类型:
https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2
此外,在创建或登录用户时,请务必使用laravel的开箱即用功能进行登录和注册.在控制台中执行以下操作时,将为您构建控制器:
php artisan make:auth
Run Code Online (Sandbox Code Playgroud)
除此之外,如果护照是一些神秘的东西,你可以随时拉入laravel/socialite包(https://github.com/laravel/socialite).它将允许您"登录(社交网络在这里)".只要这也是你想要去的路线.
结束注意:我在你的问题中看到的最突出的部分是一个人如何注册但不会登录facebook.相反,将有一个访问令牌来命中各种API端点.因此,如果我得到你说得对的话,你的目的是在返回数据时使用来自facebook的用户数据,用户被认为已登录并将获得访问令牌.所以:
使用社交名流向Facebook发送"登录facebook"请求.这将获取用户的数据并利用Facebook的一些身份验证过程.
当返回包含正文中的用户数据的请求时,通过检查运行它以确保存在数据(简单的if语句应该没问题).由于Facebook已经验证了该用户和发送的凭据,因此您应该很高兴.
您可以在登录控制器中启动内部代理(这是更干净,更安全的方式),或者您可以发出JWT(在上面的答案中发布的视频的最后5分钟内介绍了JWT).
下面是一些示例代码,可帮助您入门.
应用程序\ HTTP\\控制器验证\ LoginController.php
class LoginController extends Controller
{
// ...
protected function authenticateClient(Request $request) {
$credentials = $this->credentials($request);
$data = $request->all();
$user = User::where('email', $credentials['email'])->first();
$request->request->add([
'grant_type' => $data['grant_type'],
'client_id' => $data['client_id'],
'client_secret' => $data['client_secret'],
'username' => $credentials['email'],
'password' => $credentials['password'],
'scope' => null,
]);
$proxy = Request::create(
'oauth/token',
'POST'
);
return Route::dispatch($proxy);
}
protected function authenticated(Request $request, $user) {
return $this->authenticateClient($request);
}
protected function sendLoginResponse(Request $request)
{
$request->session()->regenerate();
$this->clearLoginAttempts($request);
return $this->authenticated($request, $this->guard()->user());
}
public function login(Request $request)
{
if ($this->guard('api')->attempt($credentials, $request->has('remember'))) {
return $this->sendLoginResponse($request);
}
}
}
Run Code Online (Sandbox Code Playgroud)以上代码用于IN CASE,您的目标是使用密码授权类型通过护照验证客户端.但是,在开枪之前我会认真看一下教程视频.如果使用laravel 5.3护照,它将帮助你解决很多问题.
| 归档时间: |
|
| 查看次数: |
23343 次 |
| 最近记录: |