codeigniter 代码点火器4屏蔽:如何颁发访问令牌

kuuvgm7e  于 2023-02-27  发布在  其他
关注(0)|答案(1)|浏览(131)

我开始使用Codeigniter 4 Shield
我将这段代码添加到了app/Config/Routes.php文件中。

$routes->get('/access/token', static function() {
    $token = auth()->user()->generateAccessToken(service('request')->getVar('token_name'));

    return json_encode(['token' => $token->raw_token]);
});

当我尝试使用URL https://example.com/access/token在Web浏览器中访问路由时,出现错误:

Call to a member function generateAccessToken() on null

由以下代码行生成:

$token = auth()->user()->generateAccessToken(service('request')->getVar('token_name'));
背景信息:
  • 我已经使用Composer安装了Codeigniter 4 Shield,运行了相应的数据库迁移,其他一切都运行良好。
  • 我的Codeigniter 4盾 “登录”“注册” 页面工作正常。
  • 如何在app/Config/Routes.php文件中自动加载generateAccessToken()?*
3qpi33ja

3qpi33ja1#

您需要提交登录凭据(电子邮件和密码)沿着HTTP POST请求,以帮助识别请求访问令牌的用户。否则,auth()->user()为空,因此出现错误。
要生成访问令牌,您需要首先对用户进行身份验证。

例如:(使用emailpassword

1.定义您的 “访问令牌” 路由。注意使用->post(...)而不是->get(...)

  • 文件:app/配置/路由.php*
$routes->post('auth/token', '\App\Controllers\Auth\LoginController::accessToken');

1.定义将处理 “访问令牌” 生成的Controller方法。Issuing the Tokens

  • 文件:app/控制器/验证/登录控制器.php*
<?php

namespace App\Controllers\Auth;

use App\Controllers\BaseController;

class LoginController extends BaseController
{
    public function accessToken()
    {
        // Validate credentials
        $rules = [
            'email' => [
                'label' => 'Auth.email',
                'rules' => config('AuthSession')->emailValidationRules,
            ],
            'password' => [
                'label' => 'Auth.password',
                'rules' => 'required',
            ],
        ];

        if (!$this->validate($rules)) {
            return $this->response
                ->setJSON(['errors' => $this->validator->getErrors()])
                ->setStatusCode(422);
        }

        if (auth()->loggedIn()) {
            auth()->logout();
        }

        // Attempt to login
        $result = auth()->attempt([
            'email' => $this->request->getPost('email'),
            'password' => $this->request->getPost('password')
        ]);
        if (!$result->isOK()) {
            return $this->response
                ->setJSON(['error' => $result->reason()])
                ->setStatusCode(401);
        }
        // Generate token and return to client
        $token = auth()->user()->generateAccessToken($this->getDeviceName());

        return $this->response
            ->setJSON(['token' => $token->raw_token]);
    }

    public function getDeviceName()
    {
        $agent = $this->request->getUserAgent();

        if ($agent->isBrowser()) {
            $currentAgent = $agent->getBrowser() . ' ' . $agent->getVersion();
        } elseif ($agent->isRobot()) {
            $currentAgent = $agent->getRobot();
        } elseif ($agent->isMobile()) {
            $currentAgent = $agent->getMobile();
        } else {
            $currentAgent = 'Unidentified User Agent';
        }

        return $agent->getPlatform() . " - " . $currentAgent;
    }
}

1.使用app/Config/Filters.php上的$filters设置保护您的/api路由。Protecting Routes

  • 从全局"session""toolbar"筛选器中排除您的 “访问令牌”"auth/token")路由以及所有API路由("api/*")。
  • 文件:app/配置/过滤器.php*
<?php

// ...

class Filters extends BaseConfig
{
    // ...

    public array $globals = [
        'before' => [
            'session' => ['except' => [
                "login*",
                "register",
                "auth/a/*",
                "auth/token",
                "api/*"
            ]],
        ],
        'after' => [
            'toolbar' => ['except' => ["auth/token", "api/*"]],
        ],
    ];

    // ...

    public array $filters = [
        'tokens' => ['before' => ["api/*"]],
    ];
}

1.向auth/token路由发出一次初始HTTP POST请求,以接收 “访问令牌”。接收到令牌后,将其存储在客户端中。即:在localStorage

$.ajax({
    url: "https://your-site-domain.com/auth/token",
    type: "POST",
    data: {
        "email": "USER-EMAIL-ADDRESS-HERE",
        "password": "USER-PASSWORD-HERE",
    },
    success: function (response) {
        window.localStorage.setItem('token', response.token);
    },
    error: function (jqXHR) {
        console.log(jqXHR.responseText);
    },
});

1.现在,您可以使用Authorization标头发送接收/存储的访问令牌沿着应用程序中所有其他受保护的API HTTP请求,而无需重新验证用户。例如:

$.ajax({
    url: "https://your-site-domain.com/api/rest/v1/employees",
    type: "GET",
    beforeSend: function (jqXHR) {
        jqXHR.setRequestHeader(
            "Authorization",
            "Bearer " + window.localStorage.getItem('token')
        );
    },
    data: {},
    success: function (response) {
        // Use the response here on success.
        // I.e: listing all employees in a table.
    },
    error: function (jqXHR) {
        console.log(jqXHR.responseText);
    },
});

相关问题