Symfony2中从外部Web API存储访问和刷新令牌的位置在哪里? [英] Where to store access and refresh token from external web API in Symfony2?

查看:47
本文介绍了Symfony2中从外部Web API存储访问和刷新令牌的位置在哪里?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个简单的Symfony2项目,该项目允许员工登录并检查新闻和其他内容.然后,我想集成一个外部系统,以显示员工是否在工作.我无法控制其他系统,但是获得了Web API(REST),以便可以检索所需的信息.

I have created a simple Symfony2 project which allows employees to log in and check news and other stuff. Then I wanted to integrate an external system that shows whether the employee is at work or not. I have no control over the other system but I got an web API (REST) so that I may retrieve the information needed.

我决定使用 GuzzleBundle 作为PHP HTTP客户端来获取我需要的信息,因为帖子(stackoverflow)中的答案.

I decided to use GuzzleBundle as the PHP HTTP Client to get the information I need because of the answers in this post (stackoverflow).

因此,我登录了Web API所需的内容:

So I logged in which is required by the web API:

$client = new GuzzleHttp\Client();
$req = $client->request("POST", "https://httpbin.org/login",  ['body' => ['user' => 'user', 'pw' => 'pw']]);
$response = json_decode($req->getBody()->getContents());

然后我使用了$ response提供的访问令牌:

And then I used the provided access token from $response:

{
    "success": true,
    "content": [
    {
        "accessToken": "x",
        "accessTokenExpires": "date",
        "refreshToken": "z",
        "refreshTokenExpires": "date"
    }]
}

要检索所需的信息,

$reqPara     = ['body' =>["accessToken" => $at, "department" => $department, "location" =>$location]];

$req = $client->request("POST", "https://httpbin.org/employees/atwork", $reqPara);
$response = json_decode($req->getBody()->getContents());

我得到了我想要的东西:

And I got what I wanted:

{
    "success": true,
    "content": [
    {
        "employee": "a",
        "status": "at work",
    },
    {
        "employee": "b",
        "status": "not at work",
    }
    ]
}

当然,我每次想知道员工是否在工作时都可以登录,但是当我可以使用访问令牌时,这似乎是一种浪费.但是,当访问令牌过期时,我又需要刷新令牌来生成新令牌,但是我应该在哪里存储这些令牌并在以后重新使用它们呢?在数据库或配置文件中?是否存在为此的标准?

And of course I can login each time I want to know if the employees is at work but that seems like a waste when I can use the access token. But then again when the access token expires I need the refresh token to generate new tokens but where do I store these tokens and re-use them later? In a database or config file? Does it exist a standard for this?

推荐答案

Dmitry Malyshenko 回答了我需要做的听到. 很明显,此令牌必须缓存,而不是存储在配置中.如何缓存-完全由您决定..."

Dmitry Malyshenko answered what I needed to hear. "It's obvious that this token must be cached, not stored in configuration. How it would be cached - it totally up to you..."

有效解决方案的示例:

  • 存储一些文件
  • 存储在数据库中
  • 仅存储在内存中(作为 您班级的财产)
  • 存储在某些键值存储中(redis, 内存缓存)
  • store in some file
  • store in a database
  • store just in memory (as a property of your class)
  • store in some key-value storage (redis, memcache)

我本应该使用 CacheComponent ,但是我目前不在Symfony中进行开发3.1所以我决定将其存储在一个最自然的数据库中.首先,我在mysql数据库中创建了一个包含用户名,密码和令牌的表.然后,我创建了专用于该表的服务.看起来像这样的简化代码:

I would have used CacheComponent but I am currently not developing in Symfony 3.1 so I decided to store in a database which felt most naturally. First I created a table with username, password and tokens in a mysql-database. Then I created a service dedicated to that table. It looks something like this simplified code:

class ExternalSiteService
{
    public function  getUsername() {
        ...
    }

    public function getPassword() {
        ...
    }

    public function getAccessToken() {
        ...
    }

    public function setAccessToken($newAccessToken) {
        ...
    }

    public function getRefreshToken() {
        $query="SELECT "
            . "eapi.refreshtoken "
            . "FROM external_api eapi";
        $connection = $this->em->getConnection();
        $statement = $connection->prepare($query);
        $statement->execute();
        $results = $statement->fetchAll();
        if ( $results ) {
            return $results;
        }
        return false;
    }

    public function setRefreshToken($newRefreshToken) {
        $query="UPDATE external_api "
            . "SET refreshtoken = :new_refreshtoken "
            . "WHERE id=1;";
        $connection = $this->em->getConnection();
        $statement = $connection->prepare($query);
        $statement->bindValue('new_refreshtoken', $newRefreshToken);
        $statement->execute();
    }
}

然后,我在控制器中做了一些逻辑说,如果访问令牌无效,则使用刷新令牌,如果刷新令牌无效,则进行新的登录尝试.如果必须获取新令牌,控制器中的此代码还将令牌存储在数据库中.

Then I made some logic in the controller that says if access token not valid use refresh token, and if refresh token not valid do a new login attempt. This code in the controller also stores the tokens in the database if we have to get new ones.

    $eapiService    = $this->get('mybundle.service.externalapi');
    $reqPara     = ['body' =>["accessToken" => $at, "department" => $department, "location" =>$location]];

    $req = $client->request("POST", "https://httpbin.org/employees/atwork", $reqPara);
    $response = json_decode($req->getBody()->getContents());

    if ($response->serverErrorMessage == "Invalid access token.") {
        $req = $client->request('POST', "https://httpbin.org/getnewtokens", ['body' => ['refreshToken' => $refreshToken]]);
        $response = json_decode($req->getBody()->getContents());

        if ($response->serverErrorMessage == "Invalid refresh token.") {
            $req = $client->request('POST', 'https://httpbin.org/login', ['body' => ['user' => $user, 'pw' => $pw]]);
            $response = json_decode($req->getBody()->getContents());
            foreach ($response->content as $contentItem) {
                $eapiService->setAccessToken($contentItem->accessToken);
                $eapiService->setRefreshToken($contentItem->refreshToken);
            }
        } else {
            foreach ($response->content as $contentItem) {
                $eapiService->setAccessToken($contentItem->accessToken);
                $eapiService->setRefreshToken($contentItem->refreshToken);
            }
        }
    }
    return array('usersatwork' => $response);

我可能还会做些事情来捕捉吞噬的异常.

I will probably also make something to catch exceptions from guzzle.

这篇关于Symfony2中从外部Web API存储访问和刷新令牌的位置在哪里?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆