token的使用
1 base64编码
1.1 什么是Base64
所谓Base64,就是说选出64个字符:小写字母a-z、大写字母A-Z、数字0-9、符号"+"、"/"(再加上作为垫字的"=",实际上是使用65个字符),作为一个基本字符集。然后,其他所有符号都转换成这个字符集中的字符。
1.2 linux base64命令
1.2.1 Linux下用base64命令编解码字符串
编码:
echo -n 'Hello World' | base64 SGVsbG8gV29ybGQ= |
解码:
echo -n 'SGVsbG8gV29ybGQ=' | base64 -d Hello World |
备注:
- echo 命令是带换行符的
- echo -n 不换行输出
- echo -n '{"alg":"HS256","typ":"JWT"}' | base64
1.2.2 base64 编解码文件
#base64编码 # base64 待编码的文件名 > 编码后的文件名 base64 1.mp3 > mymp3 #base64 解码 #base64 -d 待解码的文件名 >解码后的文件名 base64 -d mymp3>88.mp3 |
1.3 Base64和Base64Url 的区别
Base64Url是一种在Base64的基础上编码形成新的编码方式,为了编码能在网络中安全顺畅传输,需要对Base64进行的编码,特别是互联网中。
Base64Url 编码的流程:
1、明文使用BASE64进行编码 2、在Base64编码的基础上进行以下的处理: 1)去除尾部的"=" 2)把"+"替换成"-" 3)斜线"/"替换成下划线"_" |
2 跨域认证问题和JWT 实现登录原理图
2.1 跨域认证问题
互联网服务离不开用户认证。一般流程是下面这样。
- 用户向服务器发送用户名和密码。
- 服务器验证通过后,在当前对话(session)里面保存相关数据,比如用户角色、登录时间等等。
- 服务器向用户返回一个 jsession_id,写入用户的 Cookie。
- 用户随后的每一次请求,都会通过 Cookie,将 session_id 传回服务器。
- 服务器收到 session_id,找到前期保存的数据,由此得知用户的身份。
这种模式的问题在于,扩展性(scaling)不好。单机当然没有问题,如果是服务器集群,或者是跨域的服务导向架构,就要求 session 数据共享,每台服务器都能够读取 session。
举例来说,A 网站和 B 网站是同一家公司的关联服务。现在要求,用户只要在其中一个网站登录,再访问另一个网站就会自动登录,请问怎么实现?
一种解决方案是 session 数据持久化,写入数据库或别的持久层。各种服务收到请求后,都向持久层请求数据。这种方案的优点是架构清晰,缺点是工程量比较大。另外,持久层万一挂了,就会单点失败。
另一种方案是服务器索性不保存 session 数据了,所有数据都保存在客户端,每次请求都发回服务器。JWT 就是这种方案的一个代表。 服务器不存数据,客户端存,服务器解析就行了
2.2 JWT 实现登录原理图
说明:
JWT只通过算法实现对Token合法性的验证,不依赖数据库,Memcached的等存储系统,因此可以做到跨服务器验证,只要密钥和算法相同,不同服务器程序生成的Token可以互相验证。
3 JWT学习
3.1 简介
JSON Web Token(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且独立的方式,用于在各方之间作为JSON对象安全地传输信息。 此信息可以通过数字签名进行验证和信任。 JWT可以使用密钥(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。
- 官方网址:https://jwt.io/
- 调试页面:https://jwt.io/
- 学习文档:https://jwt.io/introduction/
3.2 用途
- 授权:这是我们使用JWT最广泛的应用场景。一次用户登录,后续请求将会包含JWT,对于那些合法的token,允许用户连接路由,服务和资源。目前JWT广泛应用在SSO(Single Sign On)(单点登录)上。因为他们开销很小并且可以在不同领域轻松使用。
- 信息交换:JSON Web Token是一种在各方面之间安全信息传输的好的方式 因为JWT可以签名 - 例如,使用公钥/私钥对 - 您可以确定发件人是他们所说的人。 此外,由于使用标头和有效负载计算签名,您还可以验证内容是否未被篡改。
3.3 JWT组成
一个JWT由三部分组成,各部分以点分隔:
Header(头部)-----base64Url编码的Json字符串 Payload(载荷)---base64url编码的Json字符串 Signature(签名)---使用指定算法,通过Header和Playload加盐计算的字符串 |
一个JWT看起来像下面这样:
xxxxx.yyyyy.zzzzz
下面这样: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c |
3.3.1 Header
此部分有两部分组成:
- 一部分是token的类型,目前只能是JWT
- 另一部分是签名算法,比如HMAC 、 SHA256 、 RSA
示例:
{ "alg":"HS256", "typ":"JWT" } |
base64编码命令:
echo -n '{"alg":"HS256","typ":"JWT"}' | base64 |
3.3.2 Payload
token的第二部分是payload(有效负载),其中包含claims(声明)。Claims是关于一个实体(通常是用户)和其他数据类型的声明。
claims有三种类型:registered,public,and private claims。
- Registered(已注册的声明):这些是一组预定义声明,不是强制性的,但建议使用,以提供一组有用的,可互操作的声明。 其中一些是:iss(发行人),exp(到期时间),sub(主题),aud(观众)and others。(请注意,声明名称只有三个字符,因为JWT意味着紧凑。)
JWT 规定了7个官方字段,供选用。 iss (issuer):签发人 exp (expiration time):过期时间 sub (subject):主题 aud (audience):受众 nbf (Not Before):生效时间 iat (Issued At):签发时间 jti (JWT ID):编号 除了官方字段,你还可以在这个部分定义私有字段,下面就是一个例子。 { "sub": "1234567890", "name": "John Doe", "admin": true } 注意,JWT 默认是不加密的,任何人都可以读到,所以不要把秘密信息(密码,手机号等)放在这个部分。 这个 JSON 对象也要使用 Base64URL 算法转成字符串。
|
- Public(公开声明):这些可以由使用JWT的人随意定义。 但为避免冲突,应在IANA JSON Web Token Registry中定义它们,或者将其定义为包含防冲突命名空间的URI。
- private (私人声明):这些声明是为了在同意使用它们的各方之间共享信息而创建的,并且既不是注册声明也不是公开声明。
示例:
{ "sub": "1234567890", "name": "John Doe", "admin": true } |
3.3.3 Signature(保证数据安全性的)
Signature 部分是对前两部分的签名,防止数据篡改。
首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用"点"(.)分隔,就可以返回给用户。
示例:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret) |
3.4 JWT 的使用方式【重点】
客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。
此后,客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息Authorization字段里面。
Authorization: Bearer jwt
另一种做法是,跨域的时候,JWT 就放在 POST 请求的数据体里面。
3.5 JWT 的几个特点
JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。
JWT 不加密的情况下,不能将秘密数据写入 JWT。
JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。
JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑(JWT的登出问题)。就是因为服务端无状态了
正常情况下 修改了密码后就会跳转到登录页面 :修改成功后清空浏览器保存的token了
后端怎么玩? 因为服务端不保留token 我用之前的token 还是可以继续访问的
从有状态(后端也会存一个)的变成无状态的了
我们就要把它从无状态再变成有状态了
JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。
为了减少盗用,JWT 不应该使用 HTTP 80 协议明码传输,要使用 HTTPS 443 协议传输。
我们颁发一个令牌 用户名称 用户的权限信息 这个令牌2个小时有效
Jwt只要能解析 就认为你是可用的 做不了 登出 后端不存储用户信息了 后端无状态了
4 Java类库
5 java中使用jwt
5.1 新建maven工程jwt-learn1
5.2 添加依赖
<!-- 添加jwt的依赖 --> |
5.3 编写功能类
package com.powernode.utils; |
5.4 写主类测试一下
6 JWT的总结
JWT就是一个加密的带用户信息的字符串,没学习JWT之前,我们在项目中都是返回一个基本的字符串,然后请求时带上这个字符串,再从session或者redis中(共享session)获取当前用户,学过JWT以后我们可以把用户信息直接放在字符串返回给前端,然后用户请求时带过来,我们是在服务器进行解析拿到当前用户,这就是两种登录方式,这两种方式有各自的优缺点。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
2023-01-30 kuboard管理工具安装