由于http协议是无状态的,所以可以认为客户端和服务端的所有交互都是新的请求,这就意味着当我们通过账号密码验证用户时,当下一个request请求时它就不会携带刚刚的资料,于是程序只能再次重新识别。JWT就是实现了以JSON的格式,在客户端和服务端安全的传输供认证使用的信息。
根据http协议,我们并不能知道是哪个用户发出的请求,所以为了让应用能识别,我们只能在服务器存储一份用户登录的信息,这份登录信息会在响应时传递给浏览器保存为cookie,以便下次请求时发送给应用,这样应用就能识别请求来自哪个用户了,这就是传统的基于session认证。
但是session是保存到服务器内存当中的,不能跨应用服务器共享,使得应用很难扩展,随着客户端用户量增加,独立的服务器已无法承载更多的用户,这是基于session身份认证方案的问题就会暴露出来,并且这种方案存在CSRF风险,因此随着技术的发展就有了基于Token身份认证的方案去解决这些问题。
基于token的鉴权机制类似于http协议也是无状态的,它不需要在服务端去保留用户的认证信息或者会话信息。这就意味着基于token认证机制的应用不需要去考虑用户在哪一台服务器登录了,这就为应用的扩展提供了便利,另外因为用户的信息是保存在分布式缓存中,这种方式就支持分布式水平扩展,支持高并发。
由于token是保存在Redis服务器中,使用这种方式无疑加大了对Redis缓存组件的依赖和增加了硬件资源的投资。
那么我们开始介绍JWT的特点。
服务端验证后,将部分的用户信息存放到JWT中,也就是存在token的字符串中,比如用户的email和用户的姓名等。在鉴权的流程当中,是直接从JWT中直接获取用户信息,这样减少了对Redis缓存组件的依赖,也减少了硬件资源的投入。
优点:
安全性高,防止token被伪造和篡改
自包含,减少存储开销
跨语言,支持多种语言实现
支持过期,发布者等校验
缺点:
JWT不适用存放大量信息,会造成token过长
无法作废未过期的JWT,所以需要搭配Redis使用,达到用户登出操作token即失效的要求。
一个JWT是一个字符串,其由Header(头部)、Payload(负载)和Signature(签名)三个部分组成,中间以.号分隔,其格式为Header.Payload.Signature。
按照header.payload.signature这个格式串起来,串之前注意,header和payload也要做一个base64url encoded的转换。那么最终拼出来的一个例子是:
JWT指定了七个默认claims字段供选择。
iss:发行人
sub:主题
aud:用户
exp:到期时间
nbf:在此之前不可用
iat:发布时间
jti:JWT ID用于标识该JWT
除以上默认字段外,我们还可以自定义私有字段,如下例:
{
"sub":"8208208820",
"name":"hubert",
"role":"admin"
}
按照JWT标准的说明:保留的claims都是可选的,在生成payload不强制用上面的那些claim,另外你可以按照自己的想法来定义payload的结构,不过这样搞根本没必要:第一是,如果把JWT用于认证, 那么JWT标准内规定的几个claim就足够用了,假如想往JWT里多存一些用户业务信息,比如用户名(name)和角色(role)等才需要考虑添加自定义claim;第二是,JWT标准里面针对它自己规定的claim都提供了有详细的验证规则描述,每个实现库都会参照这个描述来提供JWT的验证实现,所以如果是自定义的claim名称,那么你用到的实现库就不会主动去验证这些claim。
根据源码可以发现在校验过程中主要是校验JWT字符串的格式、过期时间、加密算法正确性等。
具体校验的源码:
1 发送JWT要用https,因为JWT本身无法保证数据安全性
2 JWT的payload中不要包含太多用户信息,特别是权限角色的信息。
3 JWT的payload中建议设定一个expire时间,且不能设置太长,为什么要设置其实和cookie为什么设置过期时间一样,都是为了安全,JWT一旦生成发出去就不可以更改,在有效期内就可以永久使用。
1.2. 认证服务器依赖
1.3. 配置文件 application.yml
1.4. 认证服务器配置(核心类AuthorizationServerConfigurerAdapter)
认证服务器配置类必须继承AuthorizationServerConfigurerAdapter类
1.4.1. 内存存储token方案
1.4.2. 配置Spring Security的安全认证
1.4.3. 自定义ClientDetailsService实现类
1.4.4. 相关实体类
1.5. gateway 网关
1.5.1 pom依赖
1.5.2. application.yml配置文件
1.5.3. security安全配置
1.5.4. gateway全局过滤器
1.5.5. 其他类
1.6. 资源服务器
1.6.1. 依赖配置
1.6.2. 资源服务器配置
继承ResourceServerConfigurerAdapter类
安全配置继承WebSecurityConfigurerAdapter
1.6.3 token过滤器
获取从网关处转发的token,填充到认证的安全上下文中,实现身份权限识别
2.2. 安全配置
2.3. 其他配置
2.4. 身份信息过滤
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)