Laravel 5 API授权,适用于使用Facebook进行授权的移动应用程序

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Laravel 5 API授权,适用于使用Facebook进行授权的移动应用程序相关的知识,希望对你有一定的参考价值。

我正在研究移动应用程序的后端部分。后端将是一个RESTful API。对我来说主要问题 - 它是授权/认证用户。

我们将在移动应用程序端使用Facebook授权(适用于ios的Facebook SDK)。这里的主要问题是:如何仅使用我们可以从Facebook获得的数据在后端实施授权?

也许有人已经得到了一些解决方案或者可以提供一些这方面的例子吗

我可以把这个过程想象成:

  1. 用户按下应用程序中的“使用FB登录”按钮,并将重定向到FB,在那里他批准连接
  2. 用户使用来自FB的一些数据(用户Facebook ID,一些用户数据和授权令牌)返回应用程序
  3. 应用程序将此数据发送到API并尝试注册/验证用户
  4. API保存授权令牌,然后在应用程序将请求发送到API时使用此令牌检查用户

我是对的还是这个逻辑错了?请告知,如果可能的话,提供一些例子。

我也找到了this guy,但不确定它会对我的情况有所帮助......

答案

所以,做了一些关于这个问题的研究,现在有了一些成果。身份验证过程现在看起来像这样:

在客户端:

  • 使用Facebook API登录并获取OAUTH2代码。
  • 将此代码交换为访问令牌。
  • 从我的API请求访问令牌,包括Facebook令牌作为参数

在API上

  • 接收访问令牌请求。
  • 使用facebook访问令牌向/我Facebook图表发出请求
  • 验证Facebook用户是否存在并与我的数据库中的用户匹配
  • 创建我自己的访问令牌,保存它并将其返回到客户端以便从此时开始使用

首先,我为用户表创建了一个迁移:

<?php

use IlluminateDatabaseSchemaBlueprint;
use IlluminateDatabaseMigrationsMigration;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id')->unique();
            $table->bigInteger('facebook_id')->unique();
            $table->string('name')->unique();
            $table->string('email')->unique();
            $table->string('password')->nullable();
            $table->string('accessToken')->nullable();
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('users');
    }
}

然后我将LaravelFacebookSdk添加到项目中,该项目是完全经过单元测试的软件包,可以轻松地将Facebook SDK v5集成到Laravel和Lumen中。

然后我添加了一些身份验证路由:

Route::group(['prefix' => '/auth' /*, 'middleware' => 'throttle:10,5'*/], function () {
    Route::get('/', 'ApiAuthController@index');
    Route::get('/base', 'ApiAuthController@baseAuth');
    Route::get('/fb', 'ApiAuthController@facebookAuth');
    Route::get('/vk', 'ApiAuthController@vkAuth');
});

并创建了一个控制器来处理这些路线:

namespace AppHttpControllers;

use AppHttpRequests;
use IlluminateHttpRequest;
use IlluminateSupportFacadesAuth;
use SammyKLaravelFacebookSdkLaravelFacebookSdk;
use AppUser;

class ApiAuthController extends Controller
{
    protected $baseAuthFailedResponse = [
        'status' => false,
        'message' => 'Base authentication failed'
    ];
    protected $facebookAuthFailedResponse = [
        'status' => false,
        'message' => 'Facebook authentication failed'
    ];
    protected $vkAuthFailedResponse = [
        'status' => false,
        'message' => 'VK authentication failed'
    ];

    /**
     * Echo function
     *
     * @param Request $request
     * @return IlluminateHttpJsonResponse
     */
    public function index(Request $request){
        return response()->json($request);
    }

    /**
     * Authorise user with base authorisation using email and password
     *
     * @param Request $request - expects fields: email, password
     * @return IlluminateHttpJsonResponse
     */
    public function baseAuth(Request $request){
        $isAuthorised = Auth::attempt(
            array(
                'email' => $request->input('email'),
                'password' => $request->input('password')
            )
        );
        if ($isAuthorised){
            return response()->json(Auth::user());
        }

        return response()->json($this->baseAuthFailedResponse);
    }

    /**
     * Authorise user using facebook accessToken received in the request
     *
     * @param Request $request - expects fields: accessToken, username, fullName, email
     * @return IlluminateHttpJsonResponse
     */
    public function facebookAuth(Request $request, LaravelFacebookSdk $fb){
        if(!Auth::check()){
            // Receive access token request.
            $accessToken = $request->input('accessToken');
            // Make a request to the /me Facebook graph using the facebook access token
            try {
                $response = $fb->get('/me?fields=id,name,email', $accessToken);
            } catch(FacebookExceptionsFacebookSDKException $e) {
                $this->facebookAuthFailedResponse['details']['message'] = $e->getMessage();
                $this->facebookAuthFailedResponse['details']['error_code'] = $e->getCode();

                return response()->json($this->facebookAuthFailedResponse);
            }

            // Verify that the Facebook user exists and match to a user in my database or create new one

            // Convert the response to a `Facebook/GraphNodes/GraphUser` collection
            $facebookUser = $response->getGraphUser();

            // Create the user if it does not exist or update the existing entry.
            // This will only work if you've added the SyncableGraphNodeTrait to your User model.
            $user = User::createOrUpdateGraphNode($facebookUser);

            Auth::login($user, true);
        }

        return response()->json(Auth::user());
    }

    public function vkAuth(Request $request){
        return response()->json($this->vkAuthFailedResponse);
    }
}

另外,正如您所看到的,我使用了由LaravelFacebookSdk提供的函数$user = User::createOrUpdateGraphNode($facebookUser);。要在我们的模型中使用它,我们应该实现SyncableGraphNodeTrait。这种方法确实可以轻松获取直接从Facebook返回的数据,并在本地数据库中创建或更新它。

<?php

namespace App;

use IlluminateFoundationAuthUser as Authenticatable;
use SammyKLaravelFacebookSdkSyncableGraphNodeTrait;

class User extends Authenticatable
{
    use SyncableGraphNodeTrait;

    /**
     * The keys of the array are the names of the fields on the Graph node.
     * The values of the array are the names of the columns in the local database.
     */
    protected static $graph_node_field_aliases = [
        'id' => 'facebook_id'
    ];

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];
}

如果有人对解决方案有任何说明,请在评论中提供。

UPD:我从this topic获得的身份验证过程描述。而且this topic非常有用。来自官方网站的API description。如何轻松记住我在this topc中找到的用户。在那里我找到了一些关于API servers on Laravel的有用信息。关于authentication with tokens的良好描述

另一答案

这个过程看起来不错。只有你必须添加的一件事 - 当你进行API调用时,确实包括Laravel CSRF token

以上是关于Laravel 5 API授权,适用于使用Facebook进行授权的移动应用程序的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 通过 Passport 实现 API 请求认证:隐式授权令牌

Laravel 5 REST API

从 curl 使用 Auth0 调用 Laravel 5.3 API 时未经授权的用户

使用 axios 的 API 请求总是未经 Laravel API 授权

Laravel 5.4建站06--API 认证系统 Passport

Laravel 5.5 - Laravel Passport 使用正确的授权类型?