不用Json web token 还能用什么?

JSON WEB TOKEN 简称 JWT 是如今最经常使用的同样校验方式.

他的做用以下

  • jwt是为了在网络应用环境传递声明而执行的一种基于json的开放标准。
  • jwt被用来在身份提供者和服务提供者间传递被认证的用户身份信息,简单来讲,就是用
  • 来验证身份的手段,例如登陆校验,像咱们以前用的cookie。
  • jwt可使用HMAC算法或者是RSA的公私秘钥对来进行签名,来保证信息的可靠性。

应用场景

在例如身份验证场景中,用户一旦登陆,接下来的每一个请求都会包含jwt,用来验证身份信息。因为通讯双方使用jwt对数据进行编码,它的信息是通过签名的,因此能够确保信息的安全性.算法

jwt对比cookie

cookie缺点mongodb

  • 客户端发请求给服务器,服务器种植cookie后,每次请求都会带上cookie,浪费带宽
  • cookie不能跨服务器访问,不支持跨域
  • 服务器要对登陆的用户对象进行存储,浪费服务器内存

jwt优势json

  • jwt是不基于状态的,不须要每次请求都带上token,节约流量
  • 服务器不须要占用内存,信息相对于可靠些
  • 能够跨服务端,能够共用

这都是业界对jwt的评价,但是jwt真的是这样的吗?

咱们先来看看JWT的是怎么生成的?JWT是一种规范.他由下面的一种结构构造而成.跨域

header.payload.signature
复制代码

JWT 的 Header 部分包含有关如何计算 JWT 签名的信息,是一个如下形式的 JSON 对象:浏览器

{
    "typ": "JWT",
    "alg": "HS256"
}
复制代码

在上面的 JSON 中,“typ”键的值指定对象是JWT,“alg”键的值指定用于建立 JWT 签名的算法。 在示例中,咱们使用 HMAC-SHA256算法(一种使用密钥的散列算法)来计算签名(在步骤3中会更详细的介绍)。安全

建立 PAYLOADbash

JWT 的 payload 部分时是存储在 JWT 内的数据。在咱们的示例中,身份验证服务器建立一个JWT,其中存储有用户信息,特别是用户ID。服务器

{
    "userId": "b08f86af-35da-48f2-8fab-cef3904660bd"
}
复制代码

在咱们的示例中,咱们只将一个声明放入 payload 中。 你能够根据须要添加任意数量的声明。JWT 规定了7个官方字段,供选用。cookie

iss (issuer):签发人
exp (expiration time):过时时间
sub (subject):主题
aud (audience):受众
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):编号
复制代码

建立 SIGNATURE网络

// signature algorithm
data = base64urlEncode( header ) + “.” + base64urlEncode( payload )
hashedData = hash( data, secret )
signature = base64urlEncode( hashedData )
复制代码

是的JWT是经过不断的计算来进行校验的.

这里的性能问题, 指的是该结构带来的请求数据变多的问题. 在jwt的使用场景中, 全部的请求都须要完整带上jwt的数据. 因为payload这部分的数据仅仅是base64后的数据, 并无作任何处理. 因此, 若是在payload中增长过多的数据, 就会致使jwt的结构变大, 从而致使请求的效率下降.

若是把token存在redie或者mongodb中也是一个不错的选择. 咱们该如何作呢?

下面我以Laravel

迁移文件以下

$table->bigIncrements('id');
            $table->integer('user_id');
            $table->string('token', 191)->default('')->comment('token');
            $table->integer('expiry_time')->default(0)->comment('到期时间');
            $table->string('ua')->default('')->comment('浏览器');
            $table->string('ip')->default('')->comment('使用者ip');
            $table->timestamps();
复制代码

在经过登陆校验成功的时候生成Token

$token = md5(uniqid(md5(microtime(true)), true));
        $token = sha1($token);

        UserTokens::create([
            'user_id' => $user->id,
            'token' => $token,
            'ip' => request()->ip(),
            'expiry_time' => time() + 2 * 60 * 60,
            'ua' => request()->userAgent()
        ]);

        return $token;
复制代码

在须要的路由注入中间件拦截器

class Authenticate extends Controller
{
    public function handle(Request $request, \Closure $next)
    {
        $Authorization = $request->header('Authorization');

        if (!$Authorization) {
            return response($this->error('请登陆', 40001));
        }

        $token = explode(' ', $Authorization);
        $token = $token[1];

        if ($this->validateToken($token)) {
            return $this->validateToken($token);
        }

        return $next($request);
    }

    protected function validateToken($token)
    {
        $dbToken = UserTokens::where('token', $token)->first();
        if ($dbToken->token != $token) {
            return response($this->error('您的信息有误!', 40010));
        } else if ($dbToken->expiry_time < time()) {
            return response($this->error('token有效期到期', 40020));
        } else if ($dbToken->ua != \request()->userAgent()) {
            return response($this->error('您的信息有误!', 40010));
        } else if ($dbToken->ip != \request()->ip()) {
            return response($this->error('您的信息有误!', 40010));
        } else {
            return false;
        }
    }
}
复制代码

这种方式也是能够的.

相关文章
相关标签/搜索