在Laravel中使用Passport设置OAuth2服务器

在本文中,我们将探讨如何使用Laravel Passport库在Laravel中设置成熟的OAuth2服务器。 我们将通过必要的服务器配置以及一个实际示例来演示如何使用OAuth2 API。

我假设您熟悉基本的OAuth2概念和流程,因为我们将在Laravel上下文中进行讨论。 实际上,Laravel Passport库使在应用程序中快速设置OAuth2服务器变得非常容易。 因此,其他第三方应用程序可以使用您的应用程序提供的API。

在本文的上半部分,我们将安装和配置必要的库,而下半部分将介绍如何在应用程序中设置演示资源以及如何从第三方应用程序中使用它们。

服务器配置

在本节中,我们将安装使Passport库与Laravel一起使用所需的依赖项。 安装后,我们需要进行很多配置,以便Laravel可以检测Passport库。

让我们继续使用composer安装Passport库。

$composer require laravel/passport

就Passport库安装而言,仅此而已。 现在,让我们确保Laravel知道这一点。

与Laravel一起使用时,您可能知道服务提供者的概念,该概念允许您在应用程序中配置服务。 因此,每当您想在Laravel应用程序中启用新服务时,只需在config/app.php添加相关的服务提供者条目。

如果您还不了解Laravel服务提供者,我强烈建议您帮个忙,并阅读这篇介绍性文章 ,其中介绍了Laravel服务提供者的基础。

在我们的例子中,我们只需要将PassportServiceProvider提供程序添加到config/app.php中的服务提供程序列表config/app.php ,如以下代码片段所示。

...
...
'providers' => [

        /*
         * Laravel Framework Service Providers...
         */
        Illuminate\Auth\AuthServiceProvider::class,
        Illuminate\Broadcasting\BroadcastServiceProvider::class,
        Illuminate\Bus\BusServiceProvider::class,
        Illuminate\Cache\CacheServiceProvider::class,
        Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
        Illuminate\Cookie\CookieServiceProvider::class,
        Illuminate\Database\DatabaseServiceProvider::class,
        Illuminate\Encryption\EncryptionServiceProvider::class,
        Illuminate\Filesystem\FilesystemServiceProvider::class,
        Illuminate\Foundation\Providers\FoundationServiceProvider::class,
        Illuminate\Hashing\HashServiceProvider::class,
        Illuminate\Mail\MailServiceProvider::class,
        Illuminate\Notifications\NotificationServiceProvider::class,
        Illuminate\Pagination\PaginationServiceProvider::class,
        Illuminate\Pipeline\PipelineServiceProvider::class,
        Illuminate\Queue\QueueServiceProvider::class,
        Illuminate\Redis\RedisServiceProvider::class,
        Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
        Illuminate\Session\SessionServiceProvider::class,
        Illuminate\Translation\TranslationServiceProvider::class,
        Illuminate\Validation\ValidationServiceProvider::class,
        Illuminate\View\ViewServiceProvider::class,

        /*
         * Package Service Providers...
         */
        Laravel\Tinker\TinkerServiceProvider::class,

        /*
         * Application Service Providers...
         */
        App\Providers\AppServiceProvider::class,
        App\Providers\AuthServiceProvider::class,
        App\Providers\BroadcastServiceProvider::class,
        App\Providers\EventServiceProvider::class,
        App\Providers\RouteServiceProvider::class,
        Laravel\Passport\PassportServiceProvider::class,
],
...
...

接下来,我们需要运行migrate artisan命令,该命令在数据库中为Passport库创建必要的表。

$php artisan migrate

确切地说,它创建数据库中的表。

oauth_access_tokens
oauth_auth_codes
oauth_clients
oauth_personal_access_clients
oauth_refresh_tokens

接下来,我们需要生成一对公钥和私钥,Passport库将使用它们来进行加密。 正如预期的那样,Passport库提供了一个手Craft.io命令来轻松创建它。

$php artisan passport:install

那应该已经在storage/oauth-public.keystorage/oauth-private.key创建了密钥。 它还创建了一些演示客户端凭据,稍后我们将再使用。

接下来 ,让我们对Laravel用于身份验证的现有User模型类进行身份验证。 为此,我们需要将HasApiTokens特性添加到User模型类。 让我们按照以下代码片段所示进行操作。

<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Passport\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];
}

HasApiTokens特征包含帮助程序方法,这些方法用于验证请求中的令牌并在当前经过身份验证的用户的上下文中检查所请求资源的范围。

此外,我们需要在Laravel应用程序中注册Passport库提供的路由。 这些路由将用于标准OAuth2操作,例如授权,请求访问令牌等。

app/Providers/AuthServiceProvider.php文件的启动方法中,让我们注册Passport库的路由。

...
...
/**
  * Register any authentication / authorization services.
  *
  * @return void
  */
public function boot()
{
    $this->registerPolicies();
    
    Passport::routes();
}
...
...

最后但并非最不重要的一点是,我们需要将config/auth.php文件中的api驱动程序从令牌更改为通行证,因为我们将使用Passport库进行API身份验证。

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

    'api' => [
        'driver' => 'passport',
        'provider' => 'users',
    ],
],

到目前为止,就OAuth2服务器配置而言,我们已经完成了所有必需的工作。

设置演示资源

在上一节中,我们进行了所有艰苦的工作来在应用程序中设置OAuth2身份验证服务器。 在本节中,我们将设置一个可以通过API调用请求的演示资源。

我们将努力使事情变得简单。 我们的演示资源返回用户信息,前提是GET请求中存在有效的uid参数。

让我们创建一个具有以下内容的控制器文件app/Http/Controllers/UserController.php

<?php
namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\User;

class UserController extends Controller
{
    public function get(Request $request)
    {
      $user_id = $request->get("uid", 0);
      $user = User::find($user_id);
      return $user;
    }
}

与往常一样,您还需要添加一个关联的路由,应该将其添加到routes/web.php文件中。 但是我们在说的是API路由,因此需要特殊对待。

API路由在routes/api.php文件中定义。 因此,让我们继续添加我们的自定义API路由,如以下代码片段所示。

<?php

use Illuminate\Http\Request;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/

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

// custom API route
Route::middleware('auth:api')->get('/user/get', 'UserController@get');

尽管我们将其定义为/user/get ,但有效的API路由是/api/user/get ,这是在该路由上请求资源时应该使用的路由。 api前缀由Laravel自动处理,您不必为此担心!

在下一节和最后一节中,我们将讨论如何创建客户端凭据并使用OAuth2 API。

如何使用OAuth2 API

现在,我们已经在应用程序中设置了OAuth2服务器,任何第三方都可以使用OAuth连接到我们的服务器并使用我们应用程序中可用的API。

首先,第三方应用程序必须在我们的应用程序中注册才能使用API​​。 换句话说,它们被视为客户端应用程序,它们将在注册时收到客户端ID和客户端密码。

Passport库提供了一个熟练的命令,可以轻松创建客户帐户。 让我们继续创建一个模拟客户帐户。

$php artisan passport:client
Which user ID should the client be assigned to?:
 > 1

 What should we name the client?:
 > Demo OAuth2 Client Account

 Where should we redirect the request after authorization? [https://localhost/auth/callback]:
 > http://localhost/oauth2_client/callback.php

New client created successfully.
Client ID: 1
Client secret: zMm0tQ9Cp7LbjK3QTgPy1pssoT1X0u7sg0YWUW01

当您运行artisan passport:client命令时,它会在创建客户帐户之前询问您几个问题。 其中,有一个重要的问题要求您提供callback URL

callback URL是授权后将用户重定向到第三方的callback URL 。 这就是应该用于交换访问令牌的授权代码的发送位置。 我们将在稍后创建该文件。

现在,我们准备在Laravel应用程序中测试OAuth2 API。

为了演示起见,我将oauth2_client在文档根目录下创建oauth2_client目录。 理想情况下,这些文件将位于要使用Laravel应用程序中的API的第三方端。

让我们使用以下内容创建oauth2_client/auth_redirection.php文件。

<?php
$query = http_build_query(array(
    'client_id' => '1',
    'redirect_uri' => 'http://localhost/oauth2_client/callback.php',
    'response_type' => 'code',
    'scope' => '',
));

header('Location: http://your-laravel-site-url/oauth/authorize?'.$query);

确保更改client_idredirect_uri参数以反映您自己的设置,即您在创建演示客户帐户时使用的设置。

接下来,让我们使用以下内容创建oauth2_client/callback.php文件。

<?php
// check if the response includes authorization_code
if (isset($_REQUEST['code']) && $_REQUEST['code'])
{
    $ch = curl_init();
    $url = 'http://your-laravel-site-url/oauth/token';

    $params = array(
        'grant_type' => 'authorization_code',
        'client_id' => '1',
        'client_secret' => 'zMm0tQ9Cp7LbjK3QTgPy1pssoT1X0u7sg0YWUW01',
        'redirect_uri' => 'http://localhost/oauth2_client/callback.php',
        'code' => $_REQUEST['code']
    );

    curl_setopt($ch,CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

    $params_string = '';

    if (is_array($params) && count($params))
    {
        foreach($params as $key=>$value) {
            $params_string .= $key.'='.$value.'&';
        }

        rtrim($params_string, '&');

        curl_setopt($ch,CURLOPT_POST, count($params));
        curl_setopt($ch,CURLOPT_POSTFIELDS, $params_string);
    }

    $result = curl_exec($ch);
    curl_close($ch);
    $response = json_decode($result);
    
    // check if the response includes access_token
    if (isset($response->access_token) && $response->access_token)
    {
        // you would like to store the access_token in the session though...
        $access_token = $response->access_token;

        // use above token to make further api calls in this session or until the access token expires
        $ch = curl_init();
        $url = 'http://your-laravel-site-url/api/user/get';
        $header = array(
        'Authorization: Bearer '. $access_token
        );
        $query = http_build_query(array('uid' => '1'));

        curl_setopt($ch,CURLOPT_URL, $url . '?' . $query);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        $result = curl_exec($ch);
        curl_close($ch);
        $response = json_decode($result);
        var_dump($result);
    }
    else
    {
        // for some reason, the access_token was not available
        // debugging goes here
    }
}

同样,请确保根据上述文件中的设置调整URL和客户端凭据。

总共如何运作

在本节中,我们将从最终用户的角度进行全面测试。 作为最终用户,您面前有两个应用程序:

  1. 第一个是您已经拥有帐户的Laravel应用程序。 它包含您可以与其他第三方应用程序共享的信息。
  2. 第二个是演示的第三方客户端应用程序auth_redirection.phpcallback.php ,它希望使用OAuth API从Laravel应用程序中获取您的信息。

该流程从第三方客户端应用程序开始。 继续并在浏览器中打开http://localhost/oauth2_client/auth_redirection.php URL,这应该将您重定向到Laravel应用程序。 如果您尚未登录Laravel应用程序,则该应用程序将首先要求您登录。

用户登录后,应用程序将显示授权页面。

如果用户授权该请求,则该用户将被重定向回http://localhost/oauth2_client/callback.php上的第三方客户端应用程序,同时将code以及包含授权代码的GET参数作为代码。

第三方应用程序收到授权代码后,便可以与Laravel应用程序交换该代码以获取访问令牌。 这正是在oauth2_client/callback.php文件的以下代码片段中oauth2_client/callback.php

$ch = curl_init();
$url = 'http://your-laravel-site-url/oauth/token';

$params = array(
    'grant_type' => 'authorization_code',
    'client_id' => '1',
    'client_secret' => 'zMm0tQ9Cp7LbjK3QTgPy1pssoT1X0u7sg0YWUW01',
    'redirect_uri' => 'http://localhost/oauth2_client/callback.php',
    'code' => $_REQUEST['code']
);

curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

$params_string = '';

if (is_array($params) && count($params))
{
    foreach($params as $key=>$value) {
        $params_string .= $key.'='.$value.'&';
    }

    rtrim($params_string, '&');

    curl_setopt($ch,CURLOPT_POST, count($params));
    curl_setopt($ch,CURLOPT_POSTFIELDS, $params_string);
}

$result = curl_exec($ch);
curl_close($ch);
$response = json_decode($result);

接下来,第三方应用程序检查CURL请求的响应,以首先查看它是否包含有效的访问令牌。

第三方应用程序一旦获得访问令牌,便可以使用该令牌进行进一步的API调用,以根据需要从Laravel应用程序请求资源。 当然,访问令牌需要在从Laravel应用程序请求资源的每个请求中传递。

我们试图模仿用例,因为第三方应用程序希望从Laravel应用程序访问用户信息。 并且我们已经在Laravel应用程序中构建了一个API端点http:// your-laravel-site-url / api / user / get来简化它。

// check if the response includes access_token
if (isset($response->access_token) && $response->access_token)
{
    // you would like to store the access_token in the session though...
    $access_token = $response->access_token;

    // use above token to make further api calls in this session or until the access token expires
    $ch = curl_init();
    $url = 'http://your-laravel-site-url/api/user/get';
    $header = array(
    'Authorization: Bearer '. $access_token
    );
    $query = http_build_query(array('uid' => '1'));

    curl_setopt($ch,CURLOPT_URL, $url . '?' . $query);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
    $result = curl_exec($ch);
    curl_close($ch);
    $response = json_decode($result);
    var_dump($result);
}

这就是您应该如何在Laravel中使用OAuth2 API的完整流程。

至此,我们到了本文的结尾。

结论

今天,我们探索了Laravel中的Passport库,该库使我们能够非常轻松地在应用程序中设置OAuth2服务器。

对于那些刚刚开始使用Laravel或希望通过扩展来扩展您的知识,网站或应用程序的人,我们可以在Envato Market中进行很多研究。

请使用以下供稿,随时分享您的想法和疑问!

翻译自: https://code.tutsplus.com/tutorials/setup-oauth2-server-using-passport-in-laravel--cms-30576

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在 Laravel ,如果想要捕捉 `OAuthServerException` 异常,可以通过在 `App\Exceptions\Handler.php` 的 `render` 方法进行处理。 具体的做法是: 1. 在 `render` 方法添加以下代码: ```php use League\OAuth2\Server\Exception\OAuthServerException; public function render($request, Throwable $e) { if ($e instanceof OAuthServerException) { return response()->json([ 'error' => $e->getCode(), 'message' => $e->getMessage() ], $e->getHttpStatusCode()); } return parent::render($request, $e); } ``` 2. 在 `app/Providers/AuthServiceProvider.php` 文件的 `boot` 方法添加以下代码: ```php use League\OAuth2\Server\Exception\OAuthServerException; public function boot() { $this->registerPolicies(); app('auth')->viaRequest('api', function ($request) { try { return some_logic_to_get_user(); } catch (OAuthServerException $e) { throw $e; } catch (\Throwable $e) { return null; } }); } ``` 这样,当 `OAuthServerException` 异常被抛出时,它将被 `render` 方法捕获并返回 JSON 格式的异常信息。同时,`AuthServiceProvider` 的 `viaRequest` 方法也可以正确地捕获 `OAuthServerException` 异常。 ### 回答2: 在Laravel 9,如果League\OAuth2\Server\Exception\OAuthServerException无法被Exceptions/Handler的捕捉,我们可以采取以下步骤来处理该问题。 首先,我们需要确保在项目使用了正确的异常处理机制。在Laravel,默认情况下,所有的异常都会被Exceptions/Handler类捕获和处理。因此,我们需要确保我们的自定义异常处理程序被正确配置。 其次,我们可以尝试使用try-catch块来捕获OAuthServerException。在我们的代码,我们可以使用try-catch块来捕获这个异常,然后采取相应的处理措施。例如,我们可以记录异常、返回特定的错误响应,或者执行其他的逻辑来处理该异常。 另外,我们可以检查OAuthServerException的源代码,看看是否有可能在异常被抛出之前进行一些处理。例如,在Laravel的AuthServiceProvider,我们可以使用OAuthServerException的before方法来注册我们自己的异常处理程序。这样,在异常被抛出之前,我们可以对它进行一些自定义的处理。 最后,如果以上方法仍然无法解决问题,我们可以在Laravel提交一个bug报告,向Laravel开发团队反馈此问题。他们可能会在后续的版本修复此问题。 综上所述,当League\OAuth2\Server\Exception\OAuthServerException绕过了Exceptions/Handler的捕获时,我们可以尝试使用try-catch块、检查源代码或向Laravel开发团队反馈问题来解决这个问题。 ### 回答3: 要解决Laravel 9League\OAuth2\Server\Exception\OAuthServerException绕过了Exceptions/Handler的捕捉问题,可以采取以下方法: 1. 第一步是检查代码是否正确配置了异常处理。确保在app/Exceptions/Handler.php文件正确编写了对OAuthServerException的异常处理代码。如果没有,则需要在这里添加相关处理逻辑。 2. 如果确认代码配置正确,但仍然无法捕捉到OAuthServerException异常,可以尝试使用try-catch语句显式捕获该异常。在调用可能引发该异常的代码段周围添加try-catch语句,以便捕获并处理该异常。 3. 另一个解决方法是通过自定义间件来捕获并处理OAuthServerException异常。创建一个间件并将其注册到应用程序的间件链。在间件的handle方法使用try-catch语句捕获OAuthServerException异常,并在catch块处理该异常。 4. 最后,还可以尝试升级Laravel版本或OAuth Server库的版本。在新版本,可能已经修复了该问题,并提供了更好的异常处理机制。 总结来说,要解决Laravel 9League\OAuth2\Server\Exception\OAuthServerException绕过Exceptions/Handler的捕捉问题,需要检查代码配置、显式捕获异常、使用自定义间件或升级Laravel版本等方法来处理该异常。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值