laravel6 內置 api 認證

api 認證

原理

  1. 註冊:用戶註冊成功後,隨機生成長字符串作爲 token,原生 token 返回給用戶。哈希後的 token 存到數據庫裏。
  2. 登陸:用戶使用賬號密碼登陸成功,隨機生成長字符串作爲 token,原生 token 返回給用戶。哈希後的 token 存到數據庫裏。
  3. 認證:將用戶傳來的 token 進行哈希,然後取數據庫中查找哈希後的 token ,找到了就認證成功,否則失敗。

創建項目與配置

composer create-project --prefer-dist laravel/laravel laravel6
php artisan migrate
添加 api_token 字段,可空,唯一,默認 null。(可直接修改,也可以創建下面的代碼片段然後遷移)
Schema::table('users', function ($table) {
    $table->string('api_token', 80)->after('password')
                        ->unique()
                        ->nullable()
                        ->default(null);
});

php artisan migrate

我們的例子還需要設置 email 可爲空,因爲我們以用戶名作爲認證的依據

設置模型可以操作 api_token 字段

# App\User.php
protected $fillable = [
    'name', 'email', 'password', 'api_token',
];

修改 api_token 這個名稱

如果修改字段名稱 api_token,請記得改配置文件 config/auth.php 中的 stroage_key

'api' => [
    'driver' => 'token',
    'provider' => 'users',
    'hash' => false,
    'storage_key' => 'api_token',
],

guard 設置爲 api,hash 設置爲 true

// config/auth.php

'defaults' => [
    'guard' => 'api',     // 默認 api 認證
    'passwords' => 'users',
],

'api' => [
    'driver' => 'token',
    'provider' => 'users',
    'hash' => true,       // 利用 SHA-256 算法哈希你的令牌
],

設置所有請求和響應都是 json 格式

php artisan make:request BaseRequest

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class BaseRequest extends FormRequest
{
    public function wantsJson(){
        return true;
    }
    
    public function expectsJson(){
        return true;
    }
    
}

// index.php
$response = $kernel->handle(
    $request = \App\Http\Requests\BaseRequest::capture()
);

編寫 api 認證代碼

Route::post('/register', 'Auth\ApiController@register');
Route::post('/login', 'Auth\ApiController@login');
Route::post('/refresh', 'Auth\ApiController@refresh');
Route::post('/logout', 'Auth\ApiController@logout');

php artisan make:controller Auth\ApiController

<?php

// email 設置可爲空
// request 和 response 都是 json 格式
// api_token 設置可插入數據庫    
    
namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;

class ApiController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth')->except('login', 'register');
    }

    protected function username()
    {
        return 'name';
    }

    public function register(Request $request)
    {
        $this->validator($request->all())->validate();

        $api_token = Str::random(80);
        $data = array_merge($request->all(), compact('api_token'));
        $this->create($data);

        return compact('api_token');
    }

    protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => ['required', 'string', 'max:255', 'unique:users',],
//            'email' => ['required', 'string', 'email', 'max:255',],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
        ]);
    }

    protected function create(array $data)
    {
        return User::forceCreate([
            'name' => $data['name'],
//            'email' => $data['email'],
            'password' => password_hash($data['password'], PASSWORD_DEFAULT),
            'api_token' => hash('sha256', $data['api_token']),
        ]);
    }

    public function logout()
    {
        auth()->user()->update(['api_token' => null]);

        return ['message' => '退出登錄成功'];
    }

    public function login()
    {
        $user = User::where($this->username(), request($this->username()))
            ->firstOrFail();

        if (!password_verify(request('password'), $user->password)) {
            return response()->json(['error' => '抱歉,賬號名或者密碼錯誤!'],
                403);
        }

        $api_token = Str::random(80);
        $user->update(['api_token' => hash('sha256', $api_token)]);

        return compact('api_token');
    }

    public function refresh()
    {
        $api_token = Str::random(80);
        auth()->user()->update(['api_token' => hash('sha256', $api_token)]);

        return compact('api_token');
    }
}

保護路由

middleware('auth:api')

給 Request 傳 token

$response = $client->request('GET', '/api/user?api_token='.$token);

$response = $client->request('POST', '/api/user', [
    'headers' => [
        'Accept' => 'application/json',
    ],
    'form_params' => [
        'api_token' => $token,
    ],
]);

$response = $client->request('POST', '/api/user', [
    'headers' => [
        'Authorization' => 'Bearer '.$token,
        'Accept' => 'application/json',
    ],
]);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章