浅谈JWT身份认证及其优缺点

一、登录模式

在介绍JWT之前,我要先介绍一下常见的几种登录模式。

1、单一服务器模式(Session)

我们登录认证成功之后,将用户信息就存放在服务端(Session),然后将其对应的session_id存储在客户端(Cookie),从Cookie中取出session_id,服务端就可以根据这个session_id获取对应的Session,从而获取存储用户信息。
其优点是:Session自动续期,用户体验较好
其缺点是:
①没有分布式架构,无法支持横向扩展。即分布式架构的情况下,其他服务器是没有办法获取到用户信息的。当然,可以使用Session共享的方式来解决这个问题。或者,可以将用户信息存储在Redis里,用一个透明令牌(字符串)作为key,并把这个令牌存储到本地(cookie、localStorage),然后通过令牌去Redis取用户信息。
②Session依赖Cookie,如果客户端禁用了Cookie,那么Session无法正常工作。其解决方法就是,可以在请求的url后面拼接上session_id,如:http://www.liuchengyin.com/test?session_id=xxx,其安全性和用户体验感较差。
③ Session依赖Cookie,Cookie无法防止CSRF(Cross Site Request Forgery):跨站请求伪造。Session认证中,Cookie是通过浏览器发送到服务端的,借助这个特性,攻击者可以通过让用户误点攻击连接(攻击者通过cookie拿到你的session_id就可以代替你的身份访问系统)达到攻击效果。

2、SSO模式(单点登录模式)

用户只需要在身份认证服务器上登录一次,你就可以访问这个单点登录中其他关联系统的应用软件的权限,同时这种实现是不需要管理员对用户登录状态或其他信息进行修改的,这意味着多个应用系统中,用户只需一次登录就可以访问所有相互信任的应用系统。
**优点:**用户身份信息独立管理,可以更好的分布式管理,可以自己扩展安全策略。
**缺点:**认证服务器访问压力会比较大

3、Token模式

Token是一种无状态、跨服务器、高性能的验证模式。用户通过用户名和密码发送请求,程序进行验证,验证通过后返回一个签名的token给客户端存储(一般localStorage),客户端每次请求都会附带上这个token(一般在Header里附带token),服务端验证这个token之后将数据返回。
优点:无状态、可扩展、支持移动设备、可跨程序调用、安全,基于标准化,你的API考研采用标准化的JSON Web Token(JWT)
缺点:占用宽带且无法在服务端进行销毁

二、JWT令牌的身份验证

1、JWT是什么?

JSON Web Token(JWT)是一个开放的行业标准(RFC 7519),它定义了一种简介的、自包含的协议格式,用于在通信双方传递JSON对象,传递的信息经过数字签名可以被验证和信任。JWT可以使用HMAC算法或使用RSA的公钥/私钥对来签名,防止被篡改。对普通信息进行加密处理后转换成JSON,转换过后的数据称为Token。

2、JWT能做什么?

①授权:一旦用户登录,每个后续请求将包括JWT,从而允许用户访问该令牌允许的路由、服务和资源。登录成功之后,生产一个JWT,其中包含用户的信息。
②信息交换:可以在各方之间安全的传输信息。

3、JWT认证和Session认证的区别

①Session认证
通过账户密码验证之后,将用户信息保存在Session。Session是保存在服务端的,下一次通过Cookie存储的session_id去Session当中取数据。
②JWT认证
通过账户密码验证之后,将用户信息转换成JWT,以Token令牌的形式传给前端,前端将其存储到Cookie中(JWT是保存在客户端的),以后每一次请求都会带上这个token,服务器获取到这个token之后进行JWT解析来读取用户数据,如果没有数据就代表没有登录。

4、JWT有哪些优缺点

优点:基于JSON,方便解析,可以在令牌中自定义丰富内容,易扩展。通过非对称加密及数字签名技术,可以防止篡改、安全性高。可以不依赖认证服务就可以完成授权。
缺点:JWT令牌较长,占存储空间比较大。

5、JWT的结构

JWT令牌由三部分组成,每部分中间使用点(.)分隔,比如:xxxxx.yyyyy.zzzzz
①Header
JWT头部分是一个描述JWT元数据的JSON对象,头部包括令牌的类型(即JWT)及使用的哈希算法(如HMAC SHA256或RSA)。
②Payload
第二部分是负载,内容也是一个JSON对象,通过Base64Url编码,得到一个字符串,这个字符串就是JWT的第二部分(负载)。
它指定了七个默认字段供选择。

iss:发行人
exp:到期时间
sub:主体
aud:用户
nbf:在此之前不可用
iat:发布时间
jti:JWT ID用于标识该JWT

除了这七个默认字段,还可以自定义私有字段

{
	"sub": "1234567890",
	"name": "456",
	"admin": true
}

但是不建议在此部分存放敏感信息,此部门可以解码还原原始内容。虽然它可以解码,但是也不能修改这个内容。
③Signature
第三部分是签名哈希部分,是对上面两部分数据签名,通过指定的算法生成哈希,以确保数据不会被篡改。首先,需要指定一个密码(secret)。该密码仅仅为保存在服务器中,并且不能向用户公开。然后,使用标头中指定的签名算法(默认情况下为HMAC SHA256)根据以下公式生成签名。

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

在这里插入图片描述

Token认证在实际使用中的一些问题

1、下列情况,token依然有效

注销、修改密码、修改用户的权限/橘色、用户账号被删除、用户被注销。
①Token一旦被发出,是没有办法销毁的,只能等到它过期。如果想要其失效,可以将token存储在缓存中,服务端每次请求都要验证token是否存在,在上述情况的逻辑里要去Redis删除对应的token,但是这违背了Token无状态的原则。
②为每个用户提供专属的token,要让token失效直接删除token即可。但是这种方式危害极大,分布式情况下每次发送新的token都需要在多台服务器同步。如果用户同时在两个浏览器打开系统,那么一个地方退出登录,其他地方都要重新进行登录。
③让token保持短暂时间,但是这种需要频繁登录。

2、token续签问题

①可以每次请求的时候在服务端检查,如果发现快要过期了,就发个新token给浏览器,浏览器每次都要检查新旧token是否一致。不一致,就替换为新的token。但是这个缺点也很大,只有在快要过期的时候那一次请求才会更新token,对客户端也不友好。
②基于第一种,可以每次请求都更新token,但这样开销太大了。
③token时间设置长一点,这仅适用于安全性不高的系统。
④服务端返回两个token,accessToken为真实token(过期时间假设为30min),refreshToken为过期时间token(过期时间假设为1天)。登录就把这两个token保存在客户端,每次访问传递accessToken,如果服务端检测到accessToken过期,就将refreshToken传给服务端,服务端创建一个新的accessToken返回个客户端保存。其缺点:需要客户端配合,用户注销需要两个token都要失效,重新请求获取token的过程中会有短暂token不可用。

总结

JWT最适合的场景是不需要服务端保存用户状态的场景,如果考虑到 token 注销和 token 续签的场景话,没有特别好的解决方案,大部分解决方案都给 token 加上了状态,这就有点类似 Session 认证了。

本人在使用JWT的时候遇到的问题就是:如果要做权限控制的时候,需要考虑权限集合存在哪里,如果存在token里是不太合适的,我是存在Redis里的。如果做的是动态权限控制,则还需要在权限更改的逻辑里将Redis缓存删去,下一次获取权限先从DB获取然后放到Redis里。

在配合SpringSecurity时,如果做的是注解控制权限,每次还得把权限集合取出来封装成SpringSecurity认识的那个权限对象,放到SecurityContextHolder.getContext()里去。

如果是动态权限控制,则每次需要取出权限和请求的url进行各种对比,通过才允许访问,还是有点麻烦的。

  • 9
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Spring Security 是一个流行的安全性框架,能够为应用程序提供身份验证和授权方案。使用 Spring Security,我们可以轻松地集成标准的安全功能,例如用户、角色和权限管理,以保护应用程序免遭攻击和非法访问。然而,传统的 Spring Security 方案通常需要使用服务器端存储和处理用户的认证信息,这给开发者带来了一些不便,例如需要管理会话和 cookie 等等。 JWT(JSON Web Token),是一种轻量的、可移植的认证授权方式,成为最新的行业标准之一。它基于 JSON 格式并加密,可以传输在 HTTP Header 中。它比传统的 Cookie 身份验证机制更安全,因为其不需要 session 必须要在同一台服务器上共享,从而不易成为 CSRF 攻击的目标。与传统的会话模式不同,JWT 方案不会在服务端保留任何关于用户会话的信息,所有的信息都是使用非对称加密方式存储在客户端,从而方便地允许不同的后端实现和服务端以及客户端的互操作。 Spring Security 与 JWT 方案结合起来,可以获得以下优势: 1. 无需服务器端保存 TokenJWT 是一种基于标准算法的 Token,所以无需在服务器上进行存储、验证或者回收。 2. 跨域方案友好:JWT 通常被允许通过 CORS 方式实现跨域访问,并且不需要使用 Cookie 或其他标准的 HTTP 表头信息。 3. 分布式系统兼容性:JWT 方案允许多种服务端进行实现,并且兼容于不同的客户端。 4. 多平台支持:不论你使用的框架或语言,只要支持生成和校验 JWT,就能兼容 Spring Security。 总之,Spring Security 和 JWT 的结合,可以让我们轻松地实现一个安全可靠的认证授权方案,大大减轻了后端服务器的运算和存储压力,还能够有效防范 CSRF 攻击。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值