摘要:看到社区常有人问用于密码验证方式来获取的问题,刚好我最近一个项目使用,也是使用的密码授权来做验证,对于如何做登录登出,以及多账号系统的认证等常用场景做一下简单的使用小总结。
看到Laravel-China社区常有人问Laravel Passport用于密码验证方式来获取Token的问题,刚好我最近一个API项目使用Laravel Dingo Api+Passport,也是使用Oauth2 的"grant_type" => "password"密码授权来做Auth验证,对于如何做登录登出,以及多账号系统的认证等常用场景做一下简单的使用小总结。
基本配置基本安装配置主要参照官方文档,具体不详细说,列出关键代码段
config/auth.php
</>复制代码
"guards" => [
"api" => [
"driver" => "passport",
"provider" => "users",
],
],
"providers" => [
"users" => [
"driver" => "eloquent",
"model" => AppModelsUser::class
],
],
Providers/AuthServiceProvider.php
</>复制代码
public function boot()
{
$this->registerPolicies();
//默认令牌发放的有效期是永久
//Passport::tokensExpireIn(Carbon::now()->addDays(2));
//Passport::refreshTokensExpireIn(Carbon::now()->addDays(4));
Passport::routes(function (RouteRegistrar $router) {
//对于密码授权的方式只要这几个路由就可以了
config(["auth.guards.api.provider" => "users"]);
$router->forAccessTokens();
});
}
Middleware/AuthenticateApi.php 自定义中间件返回
</>复制代码
auth->guard("api")->check()) {
return $this->auth->shouldUse("api");
}
throw new UnauthorizedHttpException("", "Unauthenticated");
}
}
App/Http/Kernel.php
</>复制代码
/**
* The application"s route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array
*/
protected $routeMiddleware = [
"api-auth" => AuthenticateApi::class,
......
];
}
账号验证字段不止邮箱
对于账号验证不止是数据表中的emial字段,还可能是用户名或者手机号字段只需要在User模型中添加findForPassport方法,示例代码如下:
AppModelsUsers
</>复制代码
class User extends Authenticatable implements Transformable
{
use TransformableTrait, HasApiTokens, SoftDeletes;
public function findForPassport($login)
{
return $this->orWhere("email", $login)->orWhere("phone", $login)->first();
}
}
客户端获取access_token请求只传用户名和密码
对于密码授权的方式需要提交的参数如下:
</>复制代码
$response = $http->post("http://your-app.com/oauth/token", [
"form_params" => [
"grant_type" => "password",
"client_id" => "client-id",
"client_secret" => "client-secret",
"username" => "taylor@laravel.com",
"password" => "my-password",
"scope" => "",
],
]);
但是客户端请求的时候不想把grant_type,client_id,client_secret,scope放到请求参数中或者暴露给客户端,只像JWT一样只发送username和password 怎么办?很简单我们只要将不需要请求的放到配置文件中,然后客户端请求用户名密码以后我们再向oauth/token发送请求带上相关的配置就可以了。
.env.php
</>复制代码
OAUTH_GRANT_TYPE=password
OAUTH_CLIENT_ID=1
OAUTH_CLIENT_SECRET=EvE4UPGc25TjXwv9Lmk432lpp7Uzb8G4fNJsyJ83
OAUTH_SCOPE=*
config/passport.php 当然该配置你可以配置多个client
</>复制代码
return [
"grant_type" => env("OAUTH_GRANT_TYPE"),
"client_id" => env("OAUTH_CLIENT_ID"),
"client_secret" => env("OAUTH_CLIENT_SECRET"),
"scope" => env("OAUTH_SCOPE", "*"),
];
LoginController.php的示例代码如下,因为用了Dingo Api配置了api前缀,所以请求/api/oauth/token
</>复制代码
/**
* 获取登录TOKEN
* @param LoginRequest $request
* @return IlluminateHttpJsonResponse
*/
public function token(LoginRequest $request)
{
$username = $request->get("username");
$user = User::orWhere("email", $username)->orWhere("phone", $username)->first();
if ($user && ($user->status == 0)) {
throw new UnauthorizedHttpException("", "账号已被禁用");
}
$client = new Client();
try {
$request = $client->request("POST", request()->root() . "/api/oauth/token", [
"form_params" => config("passport") + $request->only(array_keys($request->rules()))
]);
} catch (RequestException $e) {
throw new UnauthorizedHttpException("", "账号验证失败");
}
if ($request->getStatusCode() == 401) {
throw new UnauthorizedHttpException("", "账号验证失败");
}
return response()->json($request->getBody()->getContents());
}
退出登录并清除Token
对于客户端退出后并清除记录在oauth_access_tokens表中的记录,示例代码如下:
</>复制代码
/**
* 退出登录
*/
public function logout()
{
if (Auth::guard("api")->check()) {
Auth::guard("api")->user()->token()->delete();
}
return response()->json(["message" => "登出成功", "status_code" => 200, "data" => null]);
}
根据用户ID认证用户
</>复制代码
app("auth")->guard("api")->setUser(User::find($userId));
多用户表(多Auth)认证
比如针对客户表和管理员表分别做Auth认证的情况,也列出关键代码段:
</>复制代码
"guards" => [
"api" => [
"driver" => "passport",
"provider" => "users",
],
"admin_api" => [
"driver" => "passport",
"provider" => "admin_users",
],
],
"providers" => [
"users" => [
"driver" => "eloquent",
"model" => AppModelsUser::class
],
"admin_users" => [
"driver" => "eloquent",
"model" => AppModelsAdminUser::class
],
],
新建一个PasspordAdminServiceProvider来实现我们自己的PasswordGrant,别忘了添加到config/app.php的providers配置段中
AppProviders/PasspordAdminServiceProvider
</>复制代码
app->make(AdminUserPassportRepository::class),
$this->app->make(LaravelPassportBridgeRefreshTokenRepository::class)
);
$grant->setRefreshTokenTTL(Passport::refreshTokensExpireIn());
return $grant;
}
}
新建AdminUserPassportRepository,Password的验证主要通过getUserEntityByUserCredentials,它读取配置的guards对应的provider来做认证,我们重写该方法,通过传递一个参数来告诉它我们要用哪个guard来做客户端认证
</>复制代码
get("guard") ?: "api";//其实关键的就在这里,就是通过传递一个guard参数来告诉它我们是使用api还是admin_api provider来做认证
$provider = config("auth.guards.{$guard}.provider");
if (is_null($model = config("auth.providers.{$provider}.model"))) {
throw new RuntimeException("Unable to determine user model from configuration.");
}
if (method_exists($model, "findForPassport")) {
$user = (new $model)->findForPassport($username);
} else {
$user = (new $model)->where("email", $username)->first();
}
if (!$user) {
return;
} elseif (method_exists($user, "validateForPassportPasswordGrant")) {
if (!$user->validateForPassportPasswordGrant($password)) {
return;
}
} elseif (!$this->hasher->check($password, $user->password)) {
return;
}
return new User($user->getAuthIdentifier());
}
}
登录和单用户系统一样,只是在请求oauth/token的时候带上guard参数,示例代码如下:
Admin/Controllers/Auth/LoginController.php
</>复制代码
middleware("guest")->except("logout");
}
/**
* 获取登录TOKEN
* @param LoginRequest $request
* @return IlluminateHttpJsonResponse
*/
public function token(LoginRequest $request)
{
$username = $request->get("username");
$user = AdminUser::orWhere("email", $username)->orWhere("phone", $username)->first();
if ($user && ($user->status == 0)) {
throw new UnauthorizedHttpException("", "账号已被禁用");
}
$client = new Client();
try {
$request = $client->request("POST", request()->root() . "/api/oauth/token", [
"form_params" => config("passport") + $request->only(array_keys($request->rules())) + ["guard" => "admin_api"]
]);
} catch (RequestException $e) {
throw new UnauthorizedHttpException("", "账号验证失败");
}
if ($request->getStatusCode() == 401) {
throw new UnauthorizedHttpException("", "账号验证失败");
}
return response()->json($request->getBody()->getContents());
}
/**
* 退出登录
*/
public function logout()
{
if (Auth::guard("admin_api")->check()) {
Auth::guard("admin_api")->user()->token()->delete();
}
return response()->json(["message" => "登出成功", "status_code" => 200, "data" => null]);
}
}
转载请注明: 转载自Ryan是菜鸟 | LNMP技术栈笔记
如果觉得本篇文章对您十分有益,何不 打赏一下
本文链接地址: Laravel Passport API 认证使用小结
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/25579.html
showImg(https://segmentfault.com/img/bV6aHV?w=1280&h=800); 社区优秀文章 Laravel 5.5+passport 放弃 dingo 开发 API 实战,让 API 开发更省心 - 自造车轮。 API 文档神器 Swagger 介绍及在 PHP 项目中使用 - API 文档撰写方案 推荐 Laravel API 项目必须使用的 8 个...
摘要:在本教程中,我们将了解如何在应用中使用认证。当用户通过登录时,会生成令牌并将其发送给用户,该用户可用于身份验证。提供,可以毫无困难地使用认证。服务提供者我们使用的最新版本,它可以使用包发现并自动注册服务。 showImg(https://segmentfault.com/img/remote/1460000019095408?w=1000&h=526); 在本教程中,我们将了解如何在 ...
摘要:第一部分安装第一步使用安装第二步服务提供器使用框架注册自己的数据库迁移目录,因此在注册提供器后,就应该运行的迁移命令来自动创建存储客户端和令牌的数据表第三步接下来,运行命令来创建生成安全访问令牌时所需的加密密钥,同时,这条命令也会创建用于生 第一部分 安装Passport(laravel/passport) 第一步. 使用 Composer 安装 Passport :composer...
摘要:使用进行测试注册接口,注册成功后返回与用户名登录接口详情接口参考了简书浪来了的认证应用实战 安装larave laravel new passport_demo cd passport_demo && composer install 将 .env 中数据库配置修改为自己的数据库配置 DB_DATABASE=homestead DB_USERNAME=homestead DB_P...
摘要:本文来自原文链接欢迎作客我们的学习群比如说你要给你的手机用户创建,使用的是你已有的系统里的数据库,尤其是用户数据。 本文来自pilishen.com----原文链接; 欢迎作客我们的php&Laravel学习群:109256050 比如说你要给你的手机APP用户创建API,使用的是你已有的Laravel系统里的数据库,尤其是用户数据。现在我们来看一下,这里使用的是Laravel Pas...
阅读 1962·2021-09-22 15:23
阅读 3477·2021-09-04 16:45
阅读 2250·2021-07-29 14:49
阅读 2846·2019-08-30 15:44
阅读 1631·2019-08-29 16:36
阅读 1163·2019-08-29 11:03
阅读 1609·2019-08-26 13:53
阅读 583·2019-08-26 11:57