我的编程空间,编程开发者的网络收藏夹
学习永远不晚

从0构建Oauth2Server服务 之Token 编解码

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

从0构建Oauth2Server服务 之Token 编解码

Token 编解码

令牌提供了一种通过在令牌字符串本身中编码所有必要信息来避免将令牌存储在数据库中的方法。这样做的主要好处是 API 服务器能够验证访问令牌,而无需对每个 API 请求进行数据库查找,从而使 API 更容易扩展。

OAuth 2.0 Bearer Tokens 的好处是应用程序不需要知道您决定如何在您的服务中实现访问令牌。这意味着以后可以在不影响客户端的情况下更改您的实现。

如果您已经拥有一个可水平扩展的分布式数据库系统,那么您可能无法通过使用自编码令牌获得任何好处。事实上,如果您已经解决了分布式数据库问题,则使用自编码令牌只会引入新问题,因为使自编码令牌无效成为一个额外的障碍。

有很多方法可以对令牌进行自编码。您选择的实际方法只对您的实施很重要,因为令牌信息不会暴露给外部开发人员。

实现自编码令牌的最常见方法是使用 JWS 规范,创建要包含在令牌中的所有数据的 JSON 序列化表示,并使用只有授权服务器知道的私钥对生成的字符串进行签名.

JWT 访问令牌编码

下面的代码是用 PHP 编写的,并使用Firebase PHP-JWT库来编码和验证令牌。您需要包含该库才能运行示例代码实际上,授权服务器将有一个用于签署令牌的私钥,资源服务器将从授权服务器元数据中获取公钥以用于验证令牌。在这个例子中,我们每次都生成一个新的私钥,并在同一个脚本中验证令牌。实际上,您需要将私钥存储在某处以使用相同的密钥一致地签署令牌。

<?php
use \Firebase\JWT\JWT;
# Generate a private key to sign the token.
# The public key would need to be published at the authorization
# server if a separate resource server needs to validate the JWT
$private_key = openssl_pkey_new([
  'digest_alg' => 'sha256',
  'private_key_bits' => 1024,
  'private_key_type' => OPENSSL_KEYTYPE_RSA
]);
# Set the user ID of the user this token is for
$user_id = "1000";
# Set the client ID of the app that is generating this token
$client_id = 'https://example-app.com';
# Provide the list of scopes this token is valid for
$scope = 'read write';
$token_data = array(
  # Issuer (the authorization server identifier)
  'iss' => 'https://' . $_SERVER['PHP_SELF'],
  # Expires At
  'exp' => time()+7200, // Valid for 2 hours
  # Audience (The identifier of the resource server)
  'aud' => 'api://default',
  # Subject (The user ID)
  'sub' => $user_id,
  # Client ID
  'client_id' => $client_id,
  # Issued At
  'iat' => time(),
  # Identifier of this token
  'jti' => microtime(true).'.'.bin2hex(random_bytes(10)),
  # The list of OAuth scopes this token includes
  'scope' => $scope
);
$token_string = JWT::encode($token_data, $private_key, 'RS256');

这将产生一个字符串,例如:

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJodH
RwczovL2F1dGhvcml6YXRpb24tc2VydmVyLmNvbS8iLCJleHAiO
jE2MzczNDQ1NzIsImF1ZCI6ImFwaTovL2RlZmF1bHQiLCJzdWIi
OiIxMDAwIiwiY2xpZW50X2lkIjoiaHR0cHM6Ly9leGFtcGxlLWF
wcC5jb20iLCJpYXQiOjE2MzczMzczNzIsImp0aSI6IjE2MzczMz
czNzIuMjA1MS42MjBmNWEzZGMwZWJhYTA5NzMxMiIsInNjb3BlI
joicmVhZCB3cml0ZSJ9.SKDO_Gu96WeHkR_Tv0d8gFQN1SEdpN8
S_h0IJQyl_5syvpIRA5wno0VDFi34k5jbnaY5WHn6Y912IOmg6t
MO91KlYOU1MNdVhHUoPoNUzYtl_nNab7Ywe29kxgrekm-67ZInD
I8RHbSkL7Z_N9eZz_J8c3EolcsoIf-Dd5n9y_Y

该令牌由三个部分组成,以句点分隔。第一部分描述了使用的签名方法。第二部分包含令牌数据。第三部分是签名。

例如,此令牌的第一个组件是此 JSON 对象:

{
   "typ":"JWT",
   "alg":"RS256"
 }

第二个组件包含 API 端点处理请求所需的实际数据,例如用户标识和范围访问。

{
  "iss": "https://authorization-server.com/",
  "exp": 1637344572,
  "aud": "api://default",
  "sub": "1000",
  "client_id": "https://example-app.com",
  "iat": 1637337372,
  "jti": "1637337372.2051.620f5a3dc0ebaa097312",
  "scope": "read write"
}

然后对这两个部分进行 base64 编码,JWT 库计算这两个字符串的 RS256 签名,然后用句点连接所有三个部分。

解码

可以使用相同的 JWT 库验证访问令牌。该库将同时对签名进行解码和验证,如果签名无效或令牌的到期日期已过,则抛出异常。

您需要与签署令牌的私钥相对应的公钥。通常,您可以从授权服务器的元数据文档中获取它,但在本例中,我们将从之前生成的私钥中派生出公钥。

注意:任何人都可以通过对令牌字符串的中间部分进行base64解码来读取令牌信息。因此,不要在令牌中存储私人信息或您不希望用户或开发人员看到的信息,这一点很重要。如果想隐藏token信息,可以使用JSON Web Encryption spec对token中的数据进行加密。

$public_key = openssl_pkey_get_details($private_key)['key'];
try {
  # Note: You must provide the list of supported algorithms in order to prevent 
  # an attacker from bypassing the signature verification. See:
  # https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/
  $token = JWT::decode($token_string, $jwt_key, ['RS256']);
  $error = false;
} catch(\Firebase\JWT\ExpiredException $e) {
  $token = false;
  $error = 'expired';
  $error_description = 'The token has expired';
} catch(\Firebase\JWT\SignatureInvalidException $e) {
  $token = false;
  $error = 'invalid';
  $error_description = 'The token provided was malformed';
} catch(Exception $e) {
  $token = false;
  $error = 'unauthorized';
  $error_description = $e->getMessage();
}
if($error) {
  header('HTTP/1.1 401 Unauthorized');
  echo json_encode(array(
    'error'=>$error, 
    'error_description'=>$error_description
  ));
  die();
} else {
  // Now $token has all the data that we encoded in it originally
  print_r($token);
}	

Invalidating

因为令牌可以在不进行数据库查找的情况下进行验证,所以在令牌过期之前无法使其失效。您需要采取额外的步骤来使自编码的令牌无效,例如临时存储已撤销令牌的列表,这是令jti牌中声明的一种用途。有关详细信息,请参阅刷新访问令牌。

以上就是从0构建Oauth2Server服务 之Token 编解码的详细内容,更多关于Oauth2Server Token编解码的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

从0构建Oauth2Server服务 之Token 编解码

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

从0构建Oauth2Server服务 之Token 编解码

这篇文章主要为大家介绍了从0构建Oauth2Server服务之Token编解码详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-05-19

从0构建Oauth2Server服务之Refreshing-access-tokens

这篇文章主要为大家介绍了从0构建Oauth2Server服务之Refreshing-access-tokens刷新令牌示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-05-19

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录