轉載自:https://blog.csdn.net/wei_yalin/article/details/86559513
最近在學習前后端分離開發,發現 在laravel中實現前后台分離是無法無法使用 CSRF Token 認證的。因為 web 請求的用戶認證是通過Session和客戶端Cookie的實現的,而前后端分離的應用無法通過API請求將Cookie 和 CSRF Token 從前端傳遞到后端,但是還有一種解決方法,就是使用laravel自帶的 API token認證。
第一步:用戶表添加api_token字段
1、可以通過數據遷移的方式添加,像這樣:
php artisan make:migration --table=用戶表名 add_api_token
然后編寫這個遷移文件,文件位於 database/migration 中
-
class AddApiToken extends Migration
-
{
-
/**
-
* Run the migrations.
-
*
-
* @return void
-
*/
-
public
function up()
-
{
-
Schema::table(
'用戶表名',
function (Blueprint $table) {
-
$table->string(
'api_token',
200)->unique()->nullable();
-
});
-
}
-
-
/**
-
* Reverse the migrations.
-
*
-
* @return void
-
*/
-
public
function down()
-
{
-
Schema::table(
'用戶表名',
function (Blueprint $table) {
-
$table->dropColumn([
'api_token']);
-
});
-
}
-
}
然后執行遷移命令
php artisan migrate
2、或者像我這樣,直接在數據庫用戶表中添加,O(∩_∩)O哈哈~
因為 varchar 存儲的是變長數據,也就是數據的真實長度,所以不要吝嗇可以給長度設大點。
第二步、添加認證服務方
我是多表認證,每個用戶角色有一張表,所以需要添加認證服務方,在 config/auth.php 中添加。一般使用已經默認的 api 認證方就好,
第三步、給用戶模型添加生成api_token方法
-
/**
-
* 更新token
-
* @return mixed|string
-
*/
-
public
function generateToken() {
-
$this->api_token = str_random(
128);
-
$this->save();
-
-
return
$this->api_token;
-
}
第四步、在控制器中添加登錄方法
這是我的登錄認證,是基於多表的用戶認證,我是個小菜菜,細節就不給你們看了,怕你們噴我⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄。總之是在登陸驗證成功之后,生成api_token並返回就可以了。
第五步、給路由添加認證中間件
在 api.php 添加如下路由,login 不需要守衛,給 logout 和 其他需要認證的路由添加守衛就可以了(auth:admin , 對應上面的admin用戶)
-
Route::any(
'unAuth',
function () {
-
return responseToJson(
1,
'未認證或認證失敗');
-
})->name(
'unAuth');
-
-
Route::prefix(
'admin')->namespace(
'Admin')->group(
function() {
-
Route::post(
'login',
'LoginController@login');
-
Route::middleware(
'auth:admin')->group(
function() {
-
Route::post(
'logout',
'LoginController@logout');
-
Route::get(
'getMenu',
'MenuController@getMenu');
-
});
-
});
使用的是auth中間件,默認的路由我沒有O(∩_∩)O,所以需要進行修改。
修改中間件 Authenticate.php , 位於 app/Http/Middleware/Authenticate.php 。
-
class Authenticate extends Middleware
-
{
-
/**
-
* Get the path the user should be redirected to when they are not authenticated.
-
*
-
* @param \Illuminate\Http\Request $request
-
* @return string
-
*/
-
protected
function redirectTo($request)
-
{
-
if (! $request->expectsJson()) {
-
return route(
'unAuth');
-
}
-
}
-
}
現在就已經好了,在登陸之后會返回 api_token ,然后請求其他路由的時候把 api_token 當參數傳過來。這樣當請求需要認證的路由的時候如果沒有 api_token 或者 api_token 錯誤,就會跳轉到 unAuth 路由,然后返回定義好的提示信息。
第六步、退出時清除 token
-
public
function logout()
-
{
-
$user = Auth::guard(
'admin')->user();
-
-
if ($user) {
-
$user->api_token =
null;
-
$user->save();
-
}
-
-
return responseToJson(
0,
'退出成功');
-
}
還可以寫個中間件,每隔一段時間更新一下 api_token 值,同時前端也要更新 api_token 。我寫的也不是多好,可以看一下
-
/**
-
* Handle an incoming request.
-
*
-
* @param \Illuminate\Http\Request $request
-
* @param \Closure $next
-
* @param string|null $guard
-
* @return mixed
-
*/
-
public
function handle($request, Closure $next, $guard)
-
{
-
$response = $next($request);
-
-
//驗證token是否過期
-
$user = Auth::guard($guard)->user();
-
if (isTimeGreater($user->updated_token_at)){
-
$response->header(
"api_token", $user->generateToken());
-
}
-
-
return $response;
-
}