Laravel 7 教程:使用 Passport 来构建 API 授权(大量代码)

Laravel

今天我们要进行Laravel Api认证
请按照以下步骤进行应用程序身份验证和授权

第一步

执行以下命令:

composer require laravel/passport
php artisan migrate
php artisan passport:install

第二部

修改 config/auth.php 文件中的 Gurds:

...
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'passport',
            'provider' => 'users',
        ],
    ],
...

第三步

app/User.php

<?php

namespace App;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Passport\HasApiTokens;

class User extends Authenticatable {
    use Notifiable, HasApiTokens;

    /**
     * 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',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];
}

第四步

app/Repositories/User/UserRepositoryInterface.php

<?php

namespace App\Repositories\User;

use Illuminate\Http\Request;

interface UserRepositoryInterface {
    public function register(Request $request);
    public function login(Request $request);
    public function refreshToken(Request $request);
    public function details();
    public function logout(Request $request);
    public function response($data, int $statusCode);
    public function getTokenAndRefreshToken(string $email, string $password);
    public function sendRequest(string $route, array $formParams);
    public function getOClient();
}

第五步

创建 app/Repositories/User/UserRepository.php 文件

<?php

namespace App\Repositories\User;

use App\User;
use GuzzleHttp\Client;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Laravel\Passport\Client as OClient;
use GuzzleHttp\Exception\ClientException;
use App\Repositories\User\UserRepositoryInterface;

class UserRepository implements UserRepositoryInterface {
    const SUCCUSUS_STATUS_CODE = 200;
    const UNAUTHORISED_STATUS_CODE = 401;
    const BASE_URL = "http://mylemp-nginx";

    public function __construct(Client $client) {
        $this->http = $client;
    }

    public function register(Request $request) {
        $email = $request->email;
        $password = $request->password;
        $input = $request->all();
        $input['password'] = bcrypt($input['password']);
        User::create($input);
        $response = $this->getTokenAndRefreshToken($email, $password);
        return $this->response($response["data"], $response["statusCode"]);
    }

    public function login(Request $request) {
        $email = $request->email;
        $password = $request->password;

        if (Auth::attempt(['email' => $email, 'password' => $password])) {
            $response = $this->getTokenAndRefreshToken($email, $password);
            $data = $response["data"];
            $statusCode =  $response["statusCode"];
        } else {
            $data = ['error'=>'Unauthorised'];
            $statusCode =  self::UNAUTHORISED_STATUS_CODE;
        }

        return $this->response($data, $statusCode);
    }

    public function refreshToken(Request $request) {
        if (is_null($request->header('Refreshtoken'))) {
            return $this->response(['error'=>'Unauthorised'], self::UNAUTHORISED_STATUS_CODE);
        }

        $refresh_token = $request->header('Refreshtoken');
        $Oclient = $this->getOClient();
        $formParams = [ 'grant_type' => 'refresh_token',
                        'refresh_token' => $refresh_token,
                        'client_id' => $Oclient->id,
                        'client_secret' => $Oclient->secret,
                        'scope' => '*'];

        return $this->sendRequest("/oauth/token", $formParams);
    }

    public function details() {
        $user = Auth::user();
        return $this->response($user, self::SUCCUSUS_STATUS_CODE);
    }

    public function logout(Request $request) {
        $request->user()->token()->revoke();
        return $this->response(['message' => 'Successfully logged out'], self::SUCCUSUS_STATUS_CODE);
    }

    public function response($data, int $statusCode) {
        $response = ["data"=>$data, "statusCode"=>$statusCode];
        return $response;
    }

    public function getTokenAndRefreshToken(string $email, string $password) {
        $Oclient = $this->getOClient();
        $formParams = [ 'grant_type' => 'password',
                        'client_id' => $Oclient->id,
                        'client_secret' => $Oclient->secret,
                        'username' => $email,
                        'password' => $password,
                        'scope' => '*'];

        return $this->sendRequest("/oauth/token", $formParams);
    }

    public function sendRequest(string $route, array $formParams) {
        try {
            $url = self::BASE_URL.$route;
            $response = $this->http->request('POST', $url, ['form_params' => $formParams]);

            $statusCode = self::SUCCUSUS_STATUS_CODE;
            $data = json_decode((string) $response->getBody(), true);
        } catch (ClientException $e) {
            echo $e->getMessage();
            $statusCode = $e->getCode();
            $data = ['error'=>'OAuth client error'];
        }

        return ["data" => $data, "statusCode"=>$statusCode];
    }

    public function getOClient() {
        return OClient::where('password_client', 1)->first();
    }
}

第六步

app/Http/Requests/UserLoginRequest.php

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;

class UserLoginRequest extends FormRequest {
    const UNPROCESSABLE_ENTITY = 422;

    public function rules() {
        return [
            'email' => 'required|email',
            'password' => 'required',
          ];
    }

    protected function failedValidation(Validator $validator) {
        throw new HttpResponseException(response()->json($validator->errors(), self::UNPROCESSABLE_ENTITY));
    }
}

第七步

app/Http/Requests/UserRegisterRequest.php

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;

class UserRegisterRequest extends FormRequest {
    const UNPROCESSABLE_ENTITY = 422;

    public function rules() {
        return [
            'name' => 'required',
            'email' => 'required|email|unique:users',
            'password' => 'required',
            'c_password' => 'required|same:password',
          ];
    }

    protected function failedValidation(Validator $validator) {
        throw new HttpResponseException(response()->json($validator->errors(), self::UNPROCESSABLE_ENTITY));
    }
}

第八步

app/Providers/AppServiceProvider.php

<?php

namespace App\Providers;

use App\Repositories\User\UserRepository;
use App\Repositories\User\UserRepositoryInterface;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider {
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register() {
        $this->app->bind(UserRepositoryInterface::class, UserRepository::class);
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot() {
        //
    }
}

第九步

app/Providers/AuthServiceProvider.php

<?php

namespace App\Providers;

use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Laravel\Passport\Passport;

class AuthServiceProvider extends ServiceProvider {
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        // 'App\Model' => 'App\Policies\ModelPolicy',
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot() {
        $this->registerPolicies();
        Passport::routes();
    }
}

第十步

app/Http/Controllers/UserController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Requests\UserLoginRequest;
use App\Http\Requests\UserRegisterRequest;
use App\Repositories\User\UserRepositoryInterface;

class UserController extends Controller {
    const SUCCUSUS_STATUS_CODE = 200;
    const UNAUTHORISED_STATUS_CODE = 401;

    public function __construct(UserRepositoryInterface $userRepository) {
        $this->userRepository = $userRepository;
    }

    public function login(UserLoginRequest $request) {
        $response = $this->userRepository->login($request);
        return response()->json($response["data"], $response["statusCode"]);
    }

    public function register(UserRegisterRequest $request) {
        $response = $this->userRepository->register($request);
        return response()->json($response["data"], $response["statusCode"]);
    }

    public function details() {
        $response = $this->userRepository->details();
        return response()->json($response["data"], $response["statusCode"]);
    }

    public function logout(Request $request) {
        $response = $this->userRepository->logout($request);
        return response()->json($response["data"], $response["statusCode"]);
    }

    public function refreshToken(Request $request) {
        $response = $this->userRepository->refreshToken($request);
        return response()->json($response["data"], $response["statusCode"]);
    }
}

第十一步

routes/api.php

<?php

use Illuminate\Support\Facades\Route;

Route::post('login', 'UserController@login');
Route::post('register', 'UserController@register');
Route::post('refreshtoken', 'UserController@refreshToken');

Route::group(['middleware' => ['auth:api']], function () {
    Route::post('logout', 'UserController@logout');
    Route::post('details', 'UserController@details');
});

测试

打开 postman 增加请求头

Accept : application/json

然后这样处理
Alt Text

你可以在 这儿 找到源代码

今天我们要进行Laravel Api认证
请按照以下步骤进行应用程序身份验证和授权

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://dev.to/azibom/how-do-you-make-la...

译文地址:https://learnku.com/laravel/t/45708

本帖已被设为精华帖!
本文为协同翻译文章,如您发现瑕疵请点击「改进」按钮提交优化建议
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 6

1.Passport 是通过封装laravel 的Authenticate来实现的

2.流程如下 先通过AuthManger->{createTokenDriver/createSessionDriver}->createUserProvider->{createDatabaseProvider/createEloquentProvider}->{DatabaseUserProvider/EloquentUserProvider} file

3.passport依赖于tokenguard实现的 当使用个人用户PersonalAccessToken时,会调用 League\OAuth2\Server\AuthorizationValidators\BearerTokenValidator 文件来验证token里面包含的内容(包括过期时间) file

4.这里面会验证token里面带有的内容 file 5.jwt里面对token的规范 file

另外如果想要自定义redis 作为数据库存储驱动 需要覆写RedisUserProvider里面的很多方法

file

3年前 评论

我其实是想知道passport怎么做oauth的APP第三方快速登录

3年前 评论

好像很复杂啊,jwt好像相对比较容易一些啊

3年前 评论
s51983 3年前

这个很不错!反而简单了很多!

3年前 评论

密码模式为啥不能像个人令牌一样直接 $user->createToken() 就生成呢?疑惑

3年前 评论

怎么修改authentication code的长度,默认的authentication code太长了

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!