Laravel 开发 RESTful API 中篇
api_token 认证
在 Laravel
中实现 API
认证有多种方式,这里我们会使用一个非常简化的方式。
开始之前,首先添加 api_token
到 users
表:
php artisan make:migration --table=users adds_api_token_to_users_table
然后编写这个迁移文件:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddsApiTokenToUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('member', function (Blueprint $table) {
$table->string('api_token', 60)->unique()->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('member', function (Blueprint $table) {
$table->dropColumn(['api_token']);
});
}
}
最后执行迁移命令作用于数据表:
php artisan migrate
创建注册接口
好吧,再次从开天辟地说起
创建 laravel
登录认证
php artisan make:auth
php artisan migrate
这两个命令会生成用户登录注册所需要的所有东西,然后在浏览器中访问 http://your-app.test/register 即可。
接着说我们的创建接口
我们使用 RegisterController
来根据注册请求返回正确的响应。尽管 Laravel
开箱提供了认证功能,但是我们还是需要对其进行调整以便返回我们想要的响应数据。该控制器使用 RegistersUsers
来实现注册,实现逻辑如下:
public function register(Request $request)
{
$this->validator($request->all())->validate();
$this->guard()->login($user);
return $this->registered($request, $user)
?: redirect($this->redirectPath());
}
我们只需要在 RegisterController
中实现 registered
方法即可。该方法接收 $request
和 $user
参数:
protected function registered(Request $request, $user)
{
$user->generateToken();
return response()->json(['data' => $user->toArray()], 201);
}
最终 App\Http\Controllers\Auth\RegisterController
中的代码如下
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Http\Request;
use Illuminate\Auth\Events\Registered;
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* @var string
*/
protected $redirectTo = '/';
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* @param array $data
* @return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|alpha_num|between:4,8|confirmed',
'password_confirmation' => 'required|alpha_num|between:4,8'
]);
}
/**
* Create a new user instance after a valid registration.
*
* @param array $data
* @return \App\User
*/
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]);
}
public function register(Request $request)
{
$this->validator($request->all())->validate();
event(new Registered($user = $this->create($request->all())));
$this->guard()->login($user);
return $this->registered($request, $user) ?: redirect($this->redirectPath());
}
protected function registered(Request $request, $user)
{
$user->generateToken();
return response()->json(['data' => $user->toArray()], 201);
}
}
在 routes/api.php
中注册路由如下:
Route::post('register', 'Auth\[email protected]');
在上面的示例代码中,我们调用了 User 模型上的生成令牌方法,该方法现在不存在,需要手动添加:
public function generateToken()
{
$this->api_token = str_random(60);![微信图片_20181205185326.png][1]
$this->save();
return $this->api_token;
}
至此,注册接口编写完成,用户现在可以通过注册接口进行注册了,感谢 Laravel
开箱提供的认证字段验证功能,如果你需要调整验证规则的话可以到 RegisterController
中查看 validator
方法。
接下来我们可以在postman
中测验一下。
ps:在测试中,一定不要忘记在headers
中添加标红的字段。
注册说完了,我们来说说登录
和注册接口一样,可以编辑 LoginController
控制器来支持 API
认证。为此,我们需要在 LoginController
覆盖 AuthenticatesUsers trait
提供的 login
方法:
public function login(Request $request)
{
$this->validateLogin($request);
if ($this->attemptLogin($request)) {
$user = $this->guard()->user();
$user->generateToken();
return response()->json([
'data' => $user->toArray(),
]);
}
return $this->sendFailedLoginResponse($request);
}
然后在 routes/api.php
中注册登录路由:
Route::post('login', 'Auth\[email protected]');
接下来,我们用postman
来测试下登录接口
哎呦,报错了,提示我们Request
没有找到
Class App\Http\Controllers\Auth\Request does not exist
解决办法是添加use Illuminate\Http\Request;
再次请求就可以得到我们想要的数据了
{
"data": {
"id": 6,
"name": "老柴",
"email": "[email protected]",
"email_verified_at": null,
"created_at": "2018-12-05 10:51:04",
"updated_at": "2018-12-05 11:04:24",
"api_token": "S0EJSrBM4LVuhq69o95NFRxSyEHHO9vGzeODItiCfyBYYkQ8e0FbduCqi1ov"
}
}
后面就可以拿着这个 api_token
作为令牌来请求需要认证的资源了。使用我们现有的策略,请求认证资源时,如果没有 token
或 token
错误,用户将会接收到未认证响应(401)。
既然有登录,那肯定就要有退出,接下来我们就说说退出
为了形成完整闭环,下面我们来编写退出登录接口,实现思路是用户发起退出登录请求时,我们将其对应的 token
字段值从数据库移除。
首先,在 routes/api.php
中注册路由:
Route::post('logout', 'Auth\[email protected]');
然后在 Auth\LoginController.php
中编写 logout
方法:
public function logout(Request $request)
{
$user = Auth::guard('api')->user();
if ($user) {
$user->api_token = null;
$user->save();
}
return response()->json(['data' => 'User logged out.'], 200);
}
ps:不要忘记添加 use Auth;
& use App\User;
使用该策略,一旦退出,用户的所有令牌都会失效,访问需要认证的接口都会拒绝访问(通过中间件实现),这需要和前端配合来避免用户在没有访问任何内容的权限下保持登录状态。
一个闭环已经形成,接下来我们要通过中间件来完善它,也就是说通过中间件实现限制访问
api_token
创建之后,我们就可以在路由文件中应用认证中间件了:
api_token
创建之后,我们就可以在路由文件中应用认证中间件了:
Route::middleware('auth:api')
->get('/user', function (Request $request) {
return $request->user();
});
我们可以使用 $request->user()
或 Auth
门面访问当前用户:
Auth::guard('api')->user(); // 登录用户实例
Auth::guard('api')->check(); // 用户是否登录
Auth::guard('api')->id(); // 登录用户ID
接下来,我们将之前定义的会员相关路由进行分组:
Route::group(['middleware'=>'auth:api'], function () {//prefix('v1')->
Route::get('member', 'Api\[email protected]');
Route::get('member/{member}', 'Api\[email protected]');
Route::post('member', 'Api\[email protected]');
Route::put('member/{member}', 'Api\[email protected]');
Route::delete('member/{member}', 'Api\[email protected]');
});
这样就不需要为每个路由设置中间件,现在看来虽然节省不了多少时间,但随着应用体量的增长,这样做的好处是保持路由的DRY(Don't Repeat Yourself)
。
我们用 postman
再访问文章接口就需要认证了:
api_token 到此就结束了
上一篇: Laravel事件监听器Listener
下一篇: 七猫免费小说红包码是多少
推荐阅读
-
flask 开发Restful API(post和get方式实例)
-
使用SpringMVC开发Restful风格的API
-
Django+Vue开发生鲜电商平台之4.Restful API和Vue介绍
-
Yii2 advanced版API接口开发 基于RESTful架构的 配置、实现、测试
-
Laravel & Lumen RESTFul API 扩展包:Dingo API(一) -- 安装配置篇
-
Laravel & Lumen RESTFul API 扩展包:Dingo API(三) -- Response(响应)
-
Laravel & Lumen RESTFul API 扩展包:Dingo API(二) -- 创建 API Endpoint(路由)
-
Laravel & Lumen RESTFul API 扩展包:Dingo API(五) -- 转化器(Transformer)
-
Yii2开发Restful API的时候如何为不同的Module显示各自的错误格式?
-
Yii2开发Restful API的时候如何为不同的Module显示各自的错误格式?