Laravel+passport 实现API认证
1、通过Composer安装Passport
composer require laravel/passport
2、在配置文件app.php中的providers数组中注册Passport服务:
Laravel\Passport\PassportServiceProvider::class,
3、生成用于存放客户端和访问令牌的数据表
php artisan migrate
4、创建token所需的加密键
php artisan passport:install
5、添加LaravelPassportHasApiTokens trait 到 AppUser 模型
namespace App;
use Laravel\Passport\HasApiTokens;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use HasApiTokens,Notifiable;
......
}
6、在 AuthServiceProvider 的 boot 方法中调用 Passport::routes 方法
Passport::routes(
//只开放 /oauth/token);
function(RouteRegistrar $router){
$router->forAccessTokens();
},
['prefix' => 'api']
7、设置 api 认证 guard 的 driver 选项为 passport
'guards' => [
......
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
8、配置更短的令牌生命周期,可以使用 tokensExpireIn 和 refreshTokensExpireIn 方法
Passport::tokensExpireIn(Carbon::now()->addDays(15));
Passport::refreshTokensExpireIn(Carbon::now()->addDays(30));
9、创建ApiController
namespace App\Http\Controllers\Api;
use App\Http\Traits\ApiResponse;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
class ApiController extends Controller
{
use AuthenticatesUsers;
use ApiResponse;
public function __construct()
{
$this->middleware('api');
}
//调用认证接口获取授权码
protected function authenticateClient(Request $request)
{
$credentials = $this->credentials($request);
$data = $request->all();
if ($request->refresh_token) {
$request->request->add([
'grant_type' => $data['grant_type'],
'client_id' => $data['client_id'],
'client_secret' => $data['client_secret'],
'refresh_token' => $data['refresh_token'],
'scope' => ''
]);
} else {
$request->request->add([
'grant_type' => $data['grant_type'],
'client_id' => $data['client_id'],
'client_secret' => $data['client_secret'],
'email' => $data['email'],
'password' => $data['password'],
'scope' => ''
]);
}
$proxy = Request::create(
'oauth/token',
'POST'
);
$response = \Route::dispatch($proxy);
return $response;
}
/*
*重写AuthenticatesUsers部分功能函数来实现整个完整的授权流程
*/
protected function authenticated(Request $request)
{
return $this->authenticateClient($request);
}
protected function sendLoginResponse(Request $request)
{
$this->clearLoginAttempts($request);
return $this->authenticated($request);
}
protected function sendFailedLoginResponse(Request $request)
{
$msg = $request['errors'];
$code = $request['code'];
return $this->failed($msg,$code);
}
}
10、创建LoginController
<?php
/**
* Created by PhpStorm.
* User: hzh
* Date: 2018/5/1
* Time: 14:17
*/
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Api\ApiController;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\User;
use Illuminate\Support\Facades\Auth;
use Laravel\Passport\Token;
use Validator;
class LoginController extends ApiController
{
protected $successStatus = 200;
public function __construct()
{
$this->middleware('auth:api')->only([
'logout'
]);
}
// 登录用户名标示为email字段
public function username()
{
return 'email';
}
public function login(Request $request){
$user = $request->only(['password','email']);
if(count($user) != 2)return response()->json(['error_code'=>203,'error'=>'Missing Parameter']);
if(Auth::attempt(['email' => request('email'), 'password' => request('password')])){
$user = Auth::user();
$success['token'] = $user->createToken('Imagingbay')->accessToken;
$success['email'] = $user->email;
$success['uid'] = $user->id;
return response()->json(['error_code'=>0,'data' => $success], 200)->withHeaders(
[
'Accept' => 'application/json',
'Authorization' => 'Bearer '.$success['token']
]
);
}
else{
return response()->json(['error_code'=>202,'error'=>'Unauthorised'], 401);
}
}
/**
* Register api
*
* @return \Illuminate\Http\Response
*/
public function register(Request $request)
{
$validator = Validator::make($request->all(), [
'email' => 'required|string|email|max:255|unique:user_ordinary|min:4',
'password' => 'required|string|min:6|confirmed',
'password_confirmation' => 'required|same:password',
]);
if ($validator->fails()) {
return response()->json(['error'=>$validator->errors()], 401);
}
$input = $request->all();
$input['password'] = bcrypt($input['password']);
$user = User::create($input);
$success['token'] = $user->createToken('Imagingbay')->accessToken;
$success['email'] = $user->email;
$success['uid'] = $user->id;
return response()->json(['error_code'=>0,'data'=>$success], $this->successStatus);
}
/*
* 注销账号
*/
public function logout(Request $request)
{
'status_code' => 200, 'data' => null]);
$user = $this->guard()->user();
if (empty($user)) {
return response()->json(['message' => '暂未登录', 'error_code' => 20403, 'data' => null]);
}
// 获取当前登陆用户的token并且将其删除
$token = Auth::guard('api')->user()->token();
if (empty($token)) {
return response()->json(['message' => '暂无有效令牌', 'error_code' => 20403, 'data' => null]);
}
if (!empty($token->delete())) {
return response()->json(['message' => '退出成功', 'error_code' => 0, 'data' => null]);
} else {
return response()->json(['message' => '退出失败', 'error_code' => 0, 'data' => null]);
}
}
/**
* details api
*
* @return \Illuminate\Http\Response
*/
public function getDetails()
{
$user = Auth::user();
return response()->json(['success' => $user], $this->successStatus);
}
}
11、添加两个监听器
'Laravel\Passport\Events\AccessTokenCreated' => [
'App\Listeners\RevokeOldTokens',
],
'Laravel\Passport\Events\RefreshTokenCreated' => [
'App\Listeners\PruneOldTokens',
],
//执行php artisan event:generate创建监听器
12、在AppListenersRevokeOldTokens的handle中删除失效token:
DB::table('oauth_access_tokens')
->where('id', '<>', $event->tokenId)
->where('user_id', $event->userId)
->where('client_id', $event->clientId)
->delete();
13、构建路由
Route::group([
'prefix'=>'/v1',
'middleware' => ['api'],
], function () {
Route::post('user/login','Api\LoginController@login');
Route::post('user/register','Api\LoginController@register');
});
Route::group([
'prefix'=>'/v1',
'middleware' => ['auth:api'],
//指定需要传入有效访问令牌的 auth:api 中间件
], function () {
Route::get('user/logout','Api\LoginController@logout');
Route::get('user/info','User\IndexController@getInfo');//显示个人信息
});
测试:
1、注册
2、登录
3、获取用户信息
4、注销