基于 JWT 接口认证

主流的网站项目,都是前后端完全分离。一个后端提供 restful api 服务,对应多个终端,如 ios, android, h5, web,在这种情况下,是无法使用 cookie + session 进行会话管理的,可以 token 进行用户认证鉴权,因为 token 是无状态的。

JWT 概述

JSON Web Token(JWT)是一个开放标准RFC 7519,它定义了一种紧凑且独立的方式,可以在各方之间作为 JSON 对象安全地传输信息。此信息可以通过数字签名进行验证和信任。JWT可以使用密钥(使用 HMAC 算法)或使用 RSA 或 ECDSA 的公钥/私钥对进行签名。

基于 token 认证的优势。基于 token 的身份验证是无状态的,我们不将用户信息存在服务器或缓存中,减轻了服务器的压力;相比原始的 cookie + session 方式,token 更适合分布式系统的用户认证,绕开了传统的分布式 session一致性等问题;安全性高,不依赖 cookie,避免了 CSRF 攻击。

一个 JWT 实际上就是一个字符串,它由三部分组成,如下所示,它们之间以点拼接在一起,如 xxxxx.yyyyy.zzzzz

  • base64UrlEncode(Header)
  • base64UrlEncode(Payload)
  • Signature

Header 有两个部分组成,包括 token 类型和 hash 算法,对 Header 进行 Base64Url 编码,作为 JWT 的第一个部分。

{
  type: 'JWT',
  alg: 'HS256'
}

Payload 中可以添加一些 B/S 之间要传递的信息,如 userId,切记不要写例如密码这样的敏感信息,然后对 Payload 进行 Base64Url 编码,作为 JWT 的第二个部分。

Signature 是需要对 Base64 编码过的 Header, Payload 和密钥,进行算法加密,加密计算过程如下

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

通过签名可以验证 JWT 的有效性,如果被篡改过,就应该返回 401 未授权的错误提示

JWT 认证的实现过程,如下图所示:

image.png

JWT 可以保存在 localStorage 中,每次请求在 HTTP 请求时,在 Header 中加入 JWT 信息,格式如下:

Authorization: token

基于 Node.js 语言的 JWT 应用

首先在项目中安装所需的 jsonwebtoken 依赖包

npm i -S jsonwebtoken

签名和验证 token 语法如下

// 签名
jwt.sign(payload, secret,  [options, callback])
// 验证
jwt.verify(token, secret, [options, callback])

示例代码

// 签名
exports.signToken = userId => jwt.sign({ userId }, config.secret, { expiresIn: '2h' });
// 验证
exports.verifyToken = token => new Promise((resolve, reject) => {
  jwt.verify(token, config.secret, (err, decoded) => {
    if(err) reject(err);
    resolve(decoded.userId);
  });
});

通过 token 验证中间件,保证每次 api 请求,都是带有效 token 的合法请求,并将传递的信息,如 userId 挂载在 req 对象中,然后参与到业务的处理当中。

exports.authToken = function(req, res, next){
  const token = req.headers.authorization;
  utils.verifyToken(token, config.secret)
    .then(userId => {
      req.userId = userId;
      next()
    })
    .catch(err => next(err));
}

客户端对 token 的处理

客户端每次发出 http 请求,可以通过 axois 全局配置响应拦截器,检测到401未授权时,清空本地存储中的 token,重定向至登录页。

axios.interceptors.response.use(
  response => {
    return response;
  },
  error => {
    if (error.response.status === 401) {
      localStorage.removeItem('token');
      location.href = `/login?redirect=${location.href}`;
    }
    return Promise.reject(error.response.data);
  }
);

参考资料

如果这篇文章对您有帮助,记得给作者点个赞,谢谢!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,692评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,482评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,995评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,223评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,245评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,208评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,091评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,929评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,346评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,570评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,739评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,437评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,037评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,677评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,833评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,760评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,647评论 2 354

推荐阅读更多精彩内容