【问题标题】:Laravel 5 API authorization for mobile applications which uses Facebook for authorizationLaravel 5 API 授权使用 Facebook 进行授权的移动应用程序
【发布时间】:2016-08-31 06:44:40
【问题描述】:

我正在开发移动应用程序的后端部分。后端将是一个 RESTful API。我的主要问题 - 它是授权/身份验证用户。

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

也许有人已经找到了一些解决方案或者可以为此任务提供一些示例?

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

  1. 用户在应用程序中按下“使用 FB 登录”按钮并获得重定向到 FB,并在此批准连接

  2. 用户带着一些来自 FB 的数据(用户 Facebook ID、一些用户数据和授权令牌)返回到应用程序

  3. 应用程序将此数据发送到 API 并尝试注册/验证用户

  4. API 保存授权令牌,然后在应用程序向 API 发送请求时使用此令牌检查用户

我是正确的还是这个逻辑是错误的?请提供建议,如果可能,请提供一些示例。

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

【问题讨论】:

    标签: php api facebook-graph-api laravel-5 authorization


    【解决方案1】:

    所以,对这个问题做了一些研究,现在有了一些结果。身份验证过程现在如下所示:

    在客户端:

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

    在 API 上

    • 接收访问令牌请求。

    • 使用 facebook 访问权限向 /me Facebook 图发出请求 令牌

    • 验证 Facebook 用户是否存在并与我的用户匹配 数据库

    • 创建我自己的访问令牌,保存并返回给客户端 从现在开始使用

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

    <?php
    
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Database\Migrations\Migration;
    
    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 App\Http\Controllers;
    
    use App\Http\Requests;
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Auth;
    use SammyK\LaravelFacebookSdk\LaravelFacebookSdk;
    use App\User;
    
    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 \Illuminate\Http\JsonResponse
         */
        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 \Illuminate\Http\JsonResponse
         */
        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 \Illuminate\Http\JsonResponse
         */
        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(\Facebook\Exceptions\FacebookSDKException $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 Illuminate\Foundation\Auth\User as Authenticatable;
    use SammyK\LaravelFacebookSdk\SyncableGraphNodeTrait;
    
    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',
        ];
    }
    

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

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

    【讨论】:

      【解决方案2】:

      这个过程看起来不错。您只需添加一件事 - 当您进行 API 调用时,请务必包含 Laravel CSRF token

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-05
      • 2020-10-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多