在Laravel框架中,默认的用户认证守卫有两个,web和api,web守卫默认的驱动是session,而api守卫默认的驱动是token。那么,该如何使用这个token驱动?

寻找 TokenGuard

通过 Auth::guard() 这个方法,可以追溯到 token 驱动对应的类。来看Illuminate\Auth\AuthManager中的代码:

/**

* Attempt to get the guard from the local cache.

*

* @param string $name

* @return \Illuminate\Contracts\Auth\Guard|\Illuminate\Contracts\Auth\StatefulGuard

*/

public function guard($name = null)

{

$name = $name ?: $this->getDefaultDriver();

return $this->guards[$name] ?? $this->guards[$name] = $this->resolve($name);

}

/**

* Resolve the given guard.

*

* @param string $name

* @return \Illuminate\Contracts\Auth\Guard|\Illuminate\Contracts\Auth\StatefulGuard

*

* @throws \InvalidArgumentException

*/

protected function resolve($name)

{

$config = $this->getConfig($name);

if (is_null($config)) {

throw new InvalidArgumentException("Auth guard [{$name}] is not defined.");

}

if (isset($this->customCreators[$config['driver']])) {

return $this->callCustomCreator($name, $config);

}

$driverMethod = 'create'.ucfirst($config['driver']).'Driver';

if (method_exists($this, $driverMethod)) {

return $this->{$driverMethod}($name, $config);

}

throw new InvalidArgumentException("Auth driver [{$config['driver']}] for guard [{$name}] is not defined.");

}

可以看到,默认情况下就会调用到 createTokenDriver 。来看看这个方法:

public function createTokenDriver($name, $config)

{

// The token guard implements a basic API token based guard implementation

// that takes an API token field from the request and matches it to the

// user in the database or another persistence layer where users are.

$guard = new TokenGuard(

$this->createUserProvider($config['provider'] ?? null),

$this->app['request']

);

$this->app->refresh('request', $guard, 'setRequest');

return $guard;

}

显然,api守卫默认的驱动就是TokenGuard。

解读 TokenGuard

/**

* Create a new authentication guard.

*

* @param \Illuminate\Contracts\Auth\UserProvider $provider

* @param \Illuminate\Http\Request $request

* @param string $inputKey

* @param string $storageKey

* @return void

*/

public function __construct(UserProvider $provider, Request $request, $inputKey = 'api_token', $storageKey = 'api_token')

{

$this->request = $request;

$this->provider = $provider;

$this->inputKey = $inputKey;

$this->storageKey = $storageKey;

}

/**

* Get the currently authenticated user.

*

* @return \Illuminate\Contracts\Auth\Authenticatable|null

*/

public function user()

{

// If we've already retrieved the user for the current request we can just

// return it back immediately. We do not want to fetch the user data on

// every call to this method because that would be tremendously slow.

if (! is_null($this->user)) {

return $this->user;

}

$user = null;

$token = $this->getTokenForRequest();

if (! empty($token)) {

$user = $this->provider->retrieveByCredentials(

[$this->storageKey => $token]

);

}

return $this->user = $user;

}

从构造函数和 user() 方法中可以看出,默认使用

['api_token' => $token]

这个数组去获取用户,也就是说,在用户表中我们需要一个字段(默认api_token)去存储标识用户的 token。

开始使用 token 进行api认证

添加数据表字段

use Illuminate\Support\Facades\Schema;

use Illuminate\Database\Schema\Blueprint;

use Illuminate\Database\Migrations\Migration;

class AddUsersApiTokenField extends Migration

{

/**

* Run the migrations.

*

* @return void

*/

public function up()

{

Schema::table('users', function (Blueprint $table) {

$table->string('api_token', 60)->unique()->nullable()->after('password');

});

}

/**

* Reverse the migrations.

*

* @return void

*/

public function down()

{

Schema::table('users', function (Blueprint $table) {

$table->dropColumn('api_token');

});

}

}

创建登录控制器

这里不演示注册之类的,假设我们的 users 表中已经存在用户,先创建一个用于 api 登录的控制器。在每次登录的时候,更新一次用户的 api_token 。这里使用了 ThrottlesLogins ,用来控制登录的尝试次数。

namespace App\Http\Controllers\Api;

use Hash;

use App\User;

use Illuminate\Http\Request;

use App\Http\Controllers\Controller;

use Illuminate\Foundation\Auth\ThrottlesLogins;

use Illuminate\Validation\ValidationException;

class LoginController extends Controller

{

use ThrottlesLogins;

/**

* @param Request $request

* @return \Illuminate\Http\Response|void

* @throws ValidationException

*/

public function login(Request $request)

{

$this->validateLogin($request);

if ($this->hasTooManyLoginAttempts($request)) {

return $this->sendLockoutResponse($request);

}

return $this->attempLogin($request);

}

/**

* @param Request $request

*/

public function validateLogin(Request $request)

{

$this->validate($request, [

$this->username() => 'required|string',

'password' => 'required|string'

]);

}

/**

* @param Request $request

* @return \Illuminate\Http\Response|void

*/

protected function attempLogin(Request $request)

{

$this->incrementLoginAttempts($request);

$user = User::where('email', $request->email)->first();

if (!$user || !Hash::check($request->password, $user->password)) {

return $this->sendFailedLoginResponse($request);

}

// 更新 api_key

$api_token = uniqid($user->id);

$user->api_token = $api_token;

$user->save();

return $this->sendLoginResponse($request, $user);

}

/**

* @param Request $request

*/

protected function sendFailedLoginResponse(Request $request)

{

throw ValidationException::withMessages([

$this->username() => [trans('auth.failed')],

]);

}

/**

* @param Request $request

* @param User $user

* @return \Illuminate\Http\Response

*/

protected function sendLoginResponse(Request $request, User $user)

{

$this->clearLoginAttempts($request);

return \Response::make([

'user' => $user,

'token' => $user->api_token

]);

}

public function username()

{

return 'email';

}

}

添加登录路由

将 routes\api.php 修改如下:

Route::namespace('Api')->group(function () {

Route::post('login', 'LoginController@login');

}); # 登录路由

Route::middleware('auth:api')->get('/user', function (Request $request) {

return $request->user();

});

调试

测试之前先往 users 表中添加几个用户,以下是我的测试数据。

可以看到登录成功并且返回了 token 。

接下去我们使用获取到的 token 请求需要登录的接口,默认有一个,就是/user.

ok~ 已经成功返回了数据,说明登录成功了!

例子中,api_token 是通过 OAuth 2.0 Access Token 的形式传进去的,但这不是唯一的方法,可以查看 TokenGuard 中的 getTokenForRequest 这个方法,它告诉我们可以用四种不同的形式传入 api_token

总结

默认的 api token 认证虽然在文档中没有提及如何使用,但是通过查看代码,也很容易使用。但是,在我们不重写或者扩展 tokenGUard的情况下,api_token 简直就是裸奔,显然不可能就这样应用到项目中去。个人猜测,框架中提供这个功能是为了让我们更好的理解 api 认证的工作原理,方便我们开发自己需要的 guard ,而且官方文档也推荐我们使用 passport 或者 jwt 进行 api 认证。

本文出于个人对默认配置的好奇进而探究之后写下的一片文章,也借鉴了网上的部分文章(忘记查看的文章地址了,也懒得找了),如有理解不到位或者错误的,请!斧!正!

欢迎任何形式转载,记得注明出处哦!

本作品采用《CC 协议》,转载必须注明作者和本文链接

oracle access manager token,Laravel 自带的 API 守卫驱动 token 使用详解相关推荐

  1. spring boot 集成 Oracle Access Manager(OAM)单点登录

    1.介绍 Oracle Access Manager(OAM)是oracle公司开发的身份认证和资源管理解决方案.结合WebGate和OHS可实现系统间单点登录集成. oracle中间件产品可以非常方 ...

  2. Windows系统里Oracle 11g R2 Client(64bit)的下载与安装(图文详解)

    1.全网最详细的Windows系统里Oracle 11g R2 Client(64bit)的下载与安装(图文详解) 方法地址:https://www.cnblogs.com/zlslch/p/9273 ...

  3. oracle access manager token,AuthenticationManager验证原理

    AuthenticationManager相关类图 AuthenticationManager验证过程 AuthenticationManager验证过程涉及到的类和接口较多,我们就从这里开始逐一分析 ...

  4. oracle home 命令,$ORACLE_HOMEbin目录下所有命令的使用方法及命令详解

    求$ORACLE_HOME/bin目录下所有命令的使用方法及命令详解 如题. $ORACLE_HOME/bin目录下有很多命令,那我们平时用到的也不是太多,即使用到的那部分可能用法也不是完全能掌握,所 ...

  5. 九爷带你了解 nginx 日志配置指令详解

    nginx日志配置指令详解 日志对于统计排错来说非常有利的. 本文总结了nginx日志相关的配置如 access_log.log_format.open_log_file_cache.log_not_ ...

  6. 线性代数带参数的线性方程组的求法示例详解

    线性方程组的求法与示例详解 线性方程组 由n个1维未知量,m个方程组成的组合叫做线性方程组. 特别的当方程组右边的值全都是0时叫做齐次线性方程组. 增广矩阵 在系数矩阵的右边添上一列,该列由线性方程组 ...

  7. oracle不能访问管理页面,无法登录Oracle Access Manager的OAM控制台

    登录后我无法访问OAMConsole主页 . OAM安装在Centos 6.4 Server Edition上,我通过FireFox访问控制台 . 我可以毫无问题地访问控制台和企业管理器 . 但是,当 ...

  8. oracle创建用户、表空间、临时表空间、分配权限步骤详解

    首先登陆管理员账号,或者有DBA权限的用户,接下来依次: --查询所有用户 select * from dba_users; --创建新用户 create user gpmgt identified ...

  9. php manual 反射,Laravel框架源码解析之反射的使用详解

    本文实例讲述了Laravel框架源码解析之反射的使用.分享给大家供大家参考,具体如下: 前言 PHP的反射类与实例化对象作用相反,实例化是调用封装类中的方法.成员,而反射类则是拆封类中的所有方法.成员 ...

最新文章

  1. Fastlane实战(一):移动开发自动化之道
  2. Centos7部署ntp服务器同步时间以及直接将本地时间同步为北京时间
  3. 探究Facebook相似性搜索工具 faiss的原理
  4. mui switch 实现方案 让你的html 设计更贴近原生
  5. 「雕爷学编程」Arduino动手做(38)——joystick双轴摇杆模块
  6. 【Kafka】kafka AdminClient API
  7. python字符串转义表
  8. oracle大数据量迁移,分批量导入样例(fetch...bulk collect)以及forall结合使用
  9. 无人机探测雷达软硬件解决方案
  10. ssl2334 铲雪车
  11. 双android系统pcb整合,基于Android的大屏幕拼接显示系统研究与实现
  12. 理财项目中宏涌晟五个投资理财基础知识
  13. python入门和使用
  14. 网易新闻回答2021:靠差异化内容逆势增长
  15. AMiner订阅小程序上线,随时随地掌握最新科研成果
  16. 人机交互技术课程实验报告《社交点评APP》系统移动界面分析报告
  17. 使用MATLAB计算一幅图像的熵
  18. python爬取云顶之弈官网排名数据
  19. APICS与AX的Master Planning(三)---Firm Planned Orders已确认计划订单
  20. 【概率统计】用正态分布和泊松分布近似表示二项分布

热门文章

  1. 基于Angular创建后台数据模拟(译)
  2. 【笔记】分离字符串中的数字、字母和汉字
  3. FreeTextBox1.6版本控件使用总结(未完)
  4. Apriori算法进行关联分析(2)
  5. python 中 feedparser的简单用法
  6. 经典的JAVA面试题
  7. 分布式数据库——TiDB的介绍和基本原理
  8. 我为什么要这么功利?
  9. 使用adb命令查看Sqlite数据库
  10. 用lua扩展你的Nginx(写的非常好)