虾皮二面:什么是 JWT? 如何基于 JWT 进行身份验证?
zhezhongyun 2024-12-11 18:18 24 浏览
相关面试题如下:
- 什么是 JWT?为什么要用 JWT?
- JWT 由哪些部分组成?
- 如何基于 JWT 进行身份验证?
- JWT 如何防止 Token 被篡改?
- 如何加强 JWT 的安全性?
- 如何让 Token 失效?
- ......
什么是 JWT?
JWT (JSON Web Token) 是目前最流行的跨域认证解决方案,是一种基于 Token 的认证授权机制。从 JWT 的全称可以看出,JWT 本身也是 Token,一种规范化之后的 JSON 结构的 Token。
Token 自身包含了身份验证所需要的所有信息,因此,我们的服务器不需要存储 Session 信息。这显然增加了系统的可用性和伸缩性,大大减轻了服务端的压力。
可以看出,JWT 更符合设计 RESTful API 时的「Stateless(无状态)」原则 。
并且, 使用 Token 认证可以有效避免 CSRF 攻击,因为 Token 一般是存在在 localStorage 中,使用 JWT 进行身份验证的过程中是不会涉及到 Cookie 的。
我在 JWT 优缺点分析[1]这篇文章中有详细介绍到使用 JWT 做身份认证的优势和劣势。
下面是 RFC 7519[2] 对 JWT 做的较为正式的定义。
JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted. ——JSON Web Token (JWT)[3]
JWT 由哪些部分组成?
JWT 本质上就是一组字串,通过(.)切分成三个为 Base64 编码的部分:
- Header : 描述 JWT 的元数据,定义了生成签名的算法以及 Token 的类型。
- Payload : 用来存放实际需要传递的数据
- Signature(签名) :服务器通过 Payload、Header 和一个密钥(Secret)使用 Header 里面指定的签名算法(默认是 HMAC SHA256)生成。
JWT 通常是这样的:xxxxx.yyyyy.zzzzz。
示例:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
你可以在 jwt.io[4] 这个网站上对其 JWT 进行解码,解码之后得到的就是 Header、Payload、Signature 这三部分。
Header 和 Payload 都是 JSON 格式的数据,Signature 由 Payload、Header 和 Secret(密钥)通过特定的计算公式和加密算法得到。
Header
Header 通常由两部分组成:
- typ(Type):令牌类型,也就是 JWT。
- alg(Algorithm) :签名算法,比如 HS256。
示例:
{
"alg": "HS256",
"typ": "JWT"
}
JSON 形式的 Header 被转换成 Base64 编码,成为 JWT 的第一部分。
Payload
Payload 也是 JSON 格式数据,其中包含了 Claims(声明,包含 JWT 的相关信息)。
Claims 分为三种类型:
- Registered Claims(注册声明) :预定义的一些声明,建议使用,但不是强制性的。
- Public Claims(公有声明) :JWT 签发方可以自定义的声明,但是为了避免冲突,应该在 IANA JSON Web Token Registry[5] 中定义它们。
- Private Claims(私有声明) :JWT 签发方因为项目需要而自定义的声明,更符合实际项目场景使用。
下面是一些常见的注册声明:
- iss(issuer):JWT 签发方。
- iat(issued at time):JWT 签发时间。
- sub(subject):JWT 主题。
- aud(audience):JWT 接收方。
- exp(expiration time):JWT 的过期时间。
- nbf(not before time):JWT 生效时间,早于该定义的时间的 JWT 不能被接受处理。
- jti(JWT ID):JWT 唯一标识。
示例:
{
"uid": "ff1212f5-d8d1-4496-bf41-d2dda73de19a",
"sub": "1234567890",
"name": "John Doe",
"exp": 15323232,
"iat": 1516239022,
"scope": ["admin", "user"]
}
Payload 部分默认是不加密的,一定不要将隐私信息存放在 Payload 当中!!!
JSON 形式的 Payload 被转换成 Base64 编码,成为 JWT 的第二部分。
Signature
Signature 部分是对前两部分的签名,作用是防止 Token(主要是 payload) 被篡改。
这个签名的生成需要用到:
- Header + Payload。
- 存放在服务端的密钥(一定不要泄露出去)。
- 签名算法。
签名的计算公式如下:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用"点"(.)分隔,成为 JWT 的第三部分。
如何基于 JWT 进行身份验证?
在基于 Token 进行身份验证的的应用程序中,服务器通过 Payload、Header 和Secret(密钥)创建Token(令牌)并将 Token 发送给客户端。客户端接收到 Token 之后,会将其保存在 Cookie 或者 localStorage 里面,以后客户端发出的所有请求都会携带这个令牌。
简化后的步骤如下:
- 用户向服务器发送用户名、密码以及验证码用于登陆系统。
- 如果用户用户名、密码以及验证码校验正确的话,服务端会返回已经签名的 Token。
- 用户以后每次向后端发请求都在 Header 中带上这个 Token。
- 服务端检查 Token 并从中获取用户相关信息。
两点建议:
- 建议将 Token 存放在 localStorage 中,放在 Cookie 中会有 CSRF 风险。
- 请求服务端并携带 Token 的常见做法是将 Token 放在 HTTP Header 的 Authorization 字段中(Authorization: Bearer Token)。
spring-security-jwt-guide[6] 就是一个基于 JWT 来做身份认证的简单案例,感兴趣的可以看看。
JWT 如何防止 Token 被篡改?
有了签名之后,即使 Token 被泄露或者解惑,黑客也没办法同时篡改 Signature 、Header 、Payload。
这是为什么呢?因为服务端拿到 Token 之后,会解析出其中包含的 Header、Payload 以及 Signature 。服务端会根据 Header、Payload、密钥再次生成一个 Signature。拿新生成的 Signature 和 Token 中的 Signature 作对比,如果一样就说明 Header 和 Payload 没有被修改。
不过,如果服务端的秘钥也被泄露的话,黑客就可以同时篡改 Signature 、Header 、Payload 了。黑客直接修改了 Header 和 Payload 之后,再重新生成一个 Signature 就可以了。
密钥一定保管好,一定不要泄露出去。JWT 安全的核心在于签名,签名安全的核心在密钥。
如何加强 JWT 的安全性?
- 使用安全系数高的加密算法。
- 使用成熟的开源库,没必要造轮子。
- Token 存放在 localStorage 中而不是 Cookie 中,避免 CSRF 风险。
- 一定不要将隐私信息存放在 Payload 当中。
- 密钥一定保管好,一定不要泄露出去。JWT 安全的核心在于签名,签名安全的核心在密钥。
- Payload 要加入 exp (JWT 的过期时间),永久有效的 JWT 不合理。并且,JWT 的过期时间不易过长。
- ......
参考资料
[1]
JWT 优缺点分析: ./advantages&disadvantages-of-jwt.md
[2]
RFC 7519: https://tools.ietf.org/html/rfc7519
[3]
JSON Web Token (JWT): https://tools.ietf.org/html/rfc7519
[4]
jwt.io: https://jwt.io/
[5]
IANA JSON Web Token Registry: https://www.iana.org/assignments/jwt/jwt.xhtml
[6]
spring-security-jwt-guide: https://github.com/Snailclimb/spring-security-jwt-guide
- 上一篇:网页结构的类型有哪些?
- 下一篇:一文看懂Ajax,学习前端开发的同学不可错过
相关推荐
- 「魔兽世界怀旧服」精简界面,简化操作,简单实用的宏分享
-
前言大家好,我是涵叔,期待内涵。今天给大家带来一些比较实用的入门级宏分享及简单讲解。宏是什么呢,简单理解就是可以通过一些代码将多个技能通过某种逻辑或者附加按键的方式绑定到一个按键之上,以此来简化操作,...
- 微信小程序学习笔记:Page()(微信小程序page中的data)
-
Page()用来注册小程序中的一个页面,接受一个Object类型参数,其指定页面的初始数据、生命周期回调、事件处理函数等。Page方法的object参数主要构成如下:属性说明datadata是页面渲染...
- iOS开发之--监听事件全攻略(一)协议代理
-
2016年才开始没几天,IT业界大事件快播庭审,最近两天看了快播庭审,真是精彩,王欣辩护人金嘴真是绝了,话说快播辩护人的金嘴,句句金腔,我很赞同辩护人道出当今互联网业界的一些不合规矩或者不合法律的...
- 软网推荐:数据安全清除 要快还要狠
-
数据安全不仅是要保护数据不被窃取或删除,另一方面还包括清理掉的数据不能被恢复。因此,简单地删除文件或格式化磁盘的做法是不安全的。借助于两款小软件,便可做到快速而安全地清除任意文件、文件夹或磁盘分区、整...
- Axure高保真教程:通过文本框维护下拉列表选项
-
常见的用户界面元素之一是下拉列表(DropdownList),提供一组可选项供用户选择。该元素通常显示为展开的列表形式,用户可以通过单击或选择列表中的选项。对于下拉列表的选项,一般由系统代码组成,因...
- IT技工专用装备:ORICO奥睿科SATA3.0高速双硬盘底座开箱
-
作为一句长期战斗在电脑维修第一线的艺术家,来几件很Bigger的装备是非常必要的!比如这一样,就非常上档次:我买的时候259,强哥为了双12,把价格调成358了?说说奥睿科的产品,个人用过一些,感觉...
- 用markdown语法制作一个好看的网址导航页面(markdown-web-nav)
-
之前为了让谷歌浏览器里的书签放到博客markdown文件下,写过一个书签和markdown互转的小工具parse-bookmark,当初也是为了能直接在博客中生成一个网址导航的页面,方便随时...
- Apple Watch应用开发:从再造墨迹天气谈起
-
编者按:本文作者刘超在2012年加入墨迹天气,主要负责iOS平台软件开发工作。在今年年初,墨迹天气团队针对AppleWatch的硬件与交互特点,对应用做了重新设计与开发。作者从软件开发角度,分享了墨...
- WXML开发指南及最佳实践(wxml技术)
-
以下是关于WXML(WeiXinMarkupLanguage)的开发指南,涵盖基础语法、核心功能及最佳实践,帮助开发者高效构建微信小程序界面。一、WXML基础什么是WXML?OWXML...
- 「杰控软件」A045. 倍福_TCADSDLL
-
A045.倍福_TCADSDLL□支持倍福CX1000通讯,可读写变量(%Var)、%I、%Q、%M;□计算机中需先安装TwinCAT软件;□确认或修改CX1000的IP地址:...
- WPF使用基础教程(wpf教程入门系列)
-
一、WPF简介WPF:WPF即WindowsPresentationFoundation,翻译为中文“Windows呈现基础”,是微软推出的基于WindowsVista的用户界面框架,属于.NE...
- 源码推荐(01.05):自适应边界的散开按钮,Swift仿斗鱼TV
-
自适应边界的散开按钮(上传者:SnowCheng)无聊写的,接口已经留好,主要方法也注释了,大家有用就拿去。Swift仿斗鱼TV(上传者:静听雨落)感谢chenqi777提供的源码和接口在学习Swi...
- HTML DOM Form 对象(html对象方法)
-
Form对象Form对象代表一个HTML表单。在HTML文档中<form>每出现一次,Form对象就会被创建。表单用户通常用于收集用户数据,包含了input元素如:...
- 金山文档全新升级-界面篇(金山文档更新后如何恢复)
-
产品背景ProductStory云服务时代的到来万物上云、智慧互联,百万级服务器组成的云端计算时代已经到来,过去困扰个人电脑的效率、安全及规模化问题已不复存在。链接各端数据的金山文档万物皆可上云,...
- iOS开发中两个常见问题的处理(ios开发案例)
-
一、“UnknownclassXXViewControllerinInterfaceBuilderfile.”问题处理最近在静态库中写了一个XXViewController类,然后在主工程...
- 一周热门
- 最近发表
- 标签列表
-
- HTML 教程 (33)
- HTML 简介 (35)
- HTML 实例/测验 (32)
- HTML 测验 (32)
- HTML 参考手册 (28)
- JavaScript 和 HTML DOM 参考手册 (32)
- HTML 拓展阅读 (30)
- HTML常用标签 (29)
- HTML文本框样式 (31)
- HTML滚动条样式 (34)
- HTML5 浏览器支持 (33)
- HTML5 新元素 (33)
- HTML5 WebSocket (30)
- HTML5 代码规范 (32)
- HTML5 标签 (717)
- HTML5 标签 (已废弃) (75)
- HTML5电子书 (32)
- HTML5开发工具 (34)
- HTML5小游戏源码 (34)
- HTML5模板下载 (30)
- HTTP 状态消息 (33)
- HTTP 方法:GET 对比 POST (33)
- 键盘快捷键 (35)
- 标签 (226)
- HTML button formtarget 属性 (30)