令牌的使用是关于在 PHP
1 中使用 JWT。使用令牌
在许多计算机系统中,用户身份验证步骤是必不可少的。最常见的身份验证是帐户和密码身份验证,这是一个注册和登录过程。 。
在现实生活中,人们也需要身份验证。每个人都应该有身份证。想想这张身份证是从哪里来的?办过身份证的人应该都知道,一般到户口簿去公安局(不知道是不是)现在改变了?)。工作人员将核实相关信息并确认其准确性。您将获得一张身份证,有效期通常为10-20年。当需要认证时,您可以携带身份证验证来验证您的身份,例如购买火车时。机票、出境或申请其他文件。
在许多在线系统中,令牌类似于身份证。账户密码就相当于我们的账本和我们自己。我们需要检查账户密码并找回。获得token后,我们就可以使用一些需要认证的服务,而且token也是有有效期的。与身份证一样,令牌理论上应该是唯一的。
2。常见的在线认证方法
1. HTTP Basic Auth
这种方式在一些早期的Web系统中比较常见。这种类型会在浏览器中显示一个窗口,您可以在其中输入帐户和密码。这很简单。它很容易使用,但有一个缺点:不安全。账户密码实际上是以明文形式(base64encode)传输的,每次都必须携带。此外,它太丑了。 。 。
2.Cookies\Session
这种认证方式其实和我们一开始提到的身份证类似。您只需输入一次帐户密码。当认证成功后,系统会将用户信息保存在会话中,会话是服务器的本地存储功能,然后系统会生成唯一的会话id基于session并以cookie的形式发送到浏览器。
cookies 是本地浏览器存储。这个机制的作用就是存储sessionid。您也可以在不使用 cookie 的情况下保存它。早期,一些网站在不支持cookie的浏览器中添加了sessionid。在网址。
cookie中存储的Session ID实际上相当于一个ID号。每次访问网站时我们都会携带此号码。服务器可以使用该号码来查找相应会话中存储的信息。一般情况下,里面会保存一些用户。 uid等信息。
说实话,这个机制并不是什么大问题,而且大部分时间都有效。然而,cookie 的一个问题是它们不能跨域。很多大公司都有很多网站,这些网站的域名可能不同。此外,当前的移动应用程序对cookie的支持不太好,cookie本身也不支持。最后,会话的服务器存储也需要一些开销,特别是在有很多用户的情况下。还有其他缺点,我不会在这里列出,因为已经写了很多关于它们的文章。
其实我想说这个机制在大多数情况下已经足够了,尤其是对于一些中小型网站。它易于使用并且可以快速开发。
3.JWT
当我们谈论JWT时,它通常会被称为令牌。我的理解是令牌实际上是一个字符串。它可以是 jwt 令牌或 sessionid 令牌。令牌是携带身份验证信息的字符串。细绳。
网上有很多关于JWT部署的文章,而且都很相似。我们懒得在这里重复了。我将发布一个大师教程。我认为这是一个非常清晰的 JSON Web 令牌介绍教程。
简单来说,JWT 基本上是一个解决方案标准。该解决方案中的下一个令牌应由 3 部分组成:Header、Payload、Signature,其中前两部分几乎是纯文本。这是一个 json 对象,它保存一些信息并使用 base64urlencode 编码为字符串。最后一个Signature是用secret加密前两个元素的结果。默认加密算法是SHA256,这个秘密必须只有服务器知道并且需要解密。
最终生成的token是一个比较长的字符串。用户成功登录后,可以将该字符串返回给浏览器。浏览器只需在下次发出请求时携带此字符串即可。问题是怎么带呢?许多文章都讨论了插入cookie。按理来说,放入cookies和sessionid有什么区别呢?标准方法是将其放在 HTTP 请求标头的授权字段中。
服务器拿到这个字符串,首先使用base64urldecode解码前两段中的header和payload,然后使用刚才使用的加密算法和secret来验证它们是否与第三段中的签名匹配。如果不同,则说明该token是假的。如果它们相同,则可以信任负载中的信息。一般情况下,Payload会存储一些用户信息,比如uid。如果Payload需要存储一些敏感数据,例如手机号码,建议这样做。首先加密有效负载。
PHP 实践
下面我用 PHP 来做一个简单的例子:
JWT 课程:
<?php
namespace App;
class Jwt
{
private $alg = 'sha256';
private $secret = "123456";
/**
* alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT
*/
public function getHeader()
{
$header = [
'alg' => $this->alg,
'typ' => 'JWT'
];
return $this->base64urlEncode(json_encode($header, JSON_UNESCAPED_UNICODE));
}
/**
* Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。JWT 规定了7个官方字段,供选用,这里可以存放私有信息,比如uid
* @param $uid int 用户id
* @return mixed
*/
public function getPayload($uid)
{
$payload = [
'iss' => 'admin', //签发人
'exp' => time() + 600, //过期时间
'sub' => 'test', //主题
'aud' => 'every', //受众
'nbf' => time(), //生效时间
'iat' => time(), //签发时间
'jti' => 10001, //编号
'uid' => $uid, //私有信息,uid
];
return $this->base64urlEncode(json_encode($payload, JSON_UNESCAPED_UNICODE));
}
/**
* 生成token,假设现在payload里面只存一个uid
* @param $uid int
* @return string
*/
public function genToken($uid)
{
$header = $this->getHeader();
$payload = $this->getPayload($uid);
$raw = $header . '.' . $payload;
$token = $raw . '.' . hash_hmac($this->alg, $raw, $this->secret);
return $token;
}
/**
* 解密校验token,成功的话返回uid
* @param $token
* @return mixed
*/
public function verifyToken($token)
{
if (!$token) {
return false;
}
$tokenArr = explode('.', $token);
if (count($tokenArr) != 3) {
return false;
}
$header = $tokenArr[0];
$payload = $tokenArr[1];
$signature = $tokenArr[2];
$payloadArr = json_decode($this->base64urlDecode($payload), true);
if (!$payloadArr) {
return false;
}
//已过期
if (isset($payloadArr['exp']) && $payloadArr['exp'] < time()) {
return false;
}
$expected = hash_hmac($this->alg, $header . '.' . $payload, $this->secret);
//签名不对
if ($expected !== $signature) {
return false;
}
return $payloadArr['uid'];
}
/**
* 安全的base64 url编码
* @param $data
* @return string
*/
private function base64urlEncode($data)
{
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
/**
* 安全的base64 url解码
* @param $data
* @return bool|string
*/
private function base64urlDecode($data)
{
return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
}
}
复制代码
测试:
<?php
$jwt = new \App\Jwt();
//获取token
$token = $jwt->genToken(1);
//解密token
$uid = $jwt->verifyToken($token);
var_dump($uid);
复制代码
以上代码仅供参考。实际使用时,最好找一个现成的库。重新发明轮子是不可取的。 jwt 的思想是通用的,与语言无关。 github上有很多。 。 。这是 PHP 库:firebase/php-jwt。
最后说一下session和jwt的选择。如果你在网上搜索一下,你可以看到很多文章比较两者的优缺点。最重要的是,每个人都有其优点和缺点。事实上,很多公司既不是seja,也不是jwt,也许它们是。自己创建一个字符串,例如 jwt 令牌,如果该字符串可以代表用户,则将其插入到 cookie 中。
作者:wangbjun
链接:https://juejin.im/post/5c358f116fb9a049eb3c1dd5
来源:掘金
版权归作者所有。商业转载请联系作者获得许可。非商业转载请注明来源。
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。