系统设计
1. 认证与授权
-
Authentication(认证) 是验证您的身份的凭据(例如用户名/用户 ID 和密码),通过这个凭据,系统得以知道你就是你,也就是说系统存在你这个用户,也叫做身份/用户验证。(你是谁)
-
Authorization(授权) 发生在 Authentication(认证) 之后。授权嘛,光看意思大家应该就明白,它主要掌管我们访问系统的权限。比如有些特定资源只能具有特定权限的人才能访问比如 admin,有些对系统资源操作比如删除、添加、更新只能特定人才具有。(你能干什么)
二者结合使用,保证系统安全性。
2. RBAC模型
系统权限控制最常采用的访问控制模型就是 RBAC 模型 ,基于角色的权限访问控制(Role-Based Access Control)。这是一种通过角色关联权限,角色同时又关联用户的授权的方式。(都是多对多关系)
3. Cookie & Session
1. what
Cookie
和 Session
都是用来跟踪浏览器用户身份的会话方式。
Cookie
存放在客户端,一般用来保存用户信息(加密)。
-
保存
SessionId
或者Token
,向后端发送请求的时候带上Cookie
,这样后端就能取到Session
或者Token
,这样就能记录用户当前的状态了,因为 HTTP 协议是无状态的。 -
用来记录和分析用户行为。
Session
通过服务端记录用户的状态。
2. 用Session-Cookie
方案进行身份验证
适合单体环境,通过 SessionID
来实现特定的用户,一般会选择存在 Redis 中。
-
用户向服务器发送用户名、密码、验证码用于登陆系统。
-
服务器验证通过后,服务器为用户创建一个
Session
,并将Session
信息存储起来。 -
服务器向用户返回一个
SessionID
写入用户的Cookie
。 -
当用户保持登录状态时,
Cookie
将与每个后续请求一起被发送出去。 -
服务器可以将存储在
Cookie
上的SessionID
与存储在内存中或者数据库中的Session
信息进行比较,以验证用户的身份,返回给用户客户端响应信息的时候会附带用户当前的状态。
-
依赖
Session
的关键业务一定要确保客户端开启了Cookie
。 -
注意
Session
的过期时间。
3. 多服务器节点下的 Session-Cookie 怎么做?
例如:假如我们部署了两份相同的服务 A,B,用户第一次登陆的时候 ,Nginx 通过负载均衡机制将用户请求转发到 A 服务器,此时用户的 Session 信息保存在 A 服务器。结果,用户第二次访问的时候 Nginx 将请求路由到 B 服务器,由于 B 服务器没有保存 用户的 Session 信息,导致用户需要重新进行登陆。
-
每一个服务器保存的 Session 信息都是互相同步的。
-
单独使用一个所有服务器都能访问到的数据节点(比如缓存)来存放 Session 信息。
-
Spring Session 是一个用于在多个服务器之间管理会话的项目。将会话数据存储在共享的外部存储中,以实现跨服务器的会话同步和共享。
4. 没有Cookie那Session还能用吗?
一般是通过 Cookie
来保存 SessionID
,还可以将 SessionID
放在请求的 url
里面https://javaguide.cn/?Session_id=xxx
。这种方案的话可行,但是安全性和用户体验感降低。当然,为了安全你也可以对 SessionID
进行一次加密之后再传入后端。
5. 为什么Cookie防不住CSRF攻击,而Token可以?
CSRF(Cross Site Request Forgery) 跨站请求伪造:就是用你的身份去发送一些对你不友好的请求。
<a src=http://www.mybank.com/Transfer?bankId=11&money=10000>科学理财,年盈利率过万</>
如果别人通过 Cookie
拿到了 SessionId
后就可以代替你的身份访问系统了。
在我们登录成功获得 Token
之后,一般会选择存放在 localStorage
(浏览器本地存储)中。然后我们在前端通过某些方式会给每个发到后端的请求加上这个 Token
,这样就不会出现 CSRF 漏洞的问题。因为,即使你点击了非法链接发送了请求到服务端,这个非法请求是不会携带 Token
的,所以这个请求将是非法的。
但是,不论是 Cookie
还是 Token
都无法避免 跨站脚本攻击(Cross Site Scripting)XSS 。
4. JWT
1. what
JWT (JSON Web Token) 是目前最流行的跨域认证解决方案,是一种基于 Token 的认证授权机制。 从 JWT 的全称可以看出,JWT 本身也是 Token,一种规范化之后的 JSON 结构的 Token。
JWT 本质上就是一组字符串,通过(.
)切分成三个为 Base64 编码的部分:
-
Header : 描述 JWT 的元数据,定义了生成签名的算法以及
Token
的类型。 -
Payload : 用来存放实际需要传递的数据
-
Signature(签名):服务器通过 Payload、Header 和一个密钥使用 Header 里面指定的签名算法(默认是 HMAC SHA256)生成。(防止JWT被篡改)
JWT 通常是这样的:xxxxx.yyyyy.zzzzz
。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ. SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
2. 身份验证
服务器通过 Payload、Header 和 Secret(密钥)创建 JWT 并将 JWT 发送给客户端。 客户端接收到 JWT 之后,会将其保存在 Cookie 或者 localStorage 里面,以后客户端发出的所有请求都会携带这个令牌。
请求服务端并携带 JWT 的常见做法是将其放在 HTTP Header 的 Authorization
字段中(Authorization: Bearer Token
)。
3. 如何防止JWT被篡改?
因为服务端拿到 JWT 之后,会解析出其中包含的 Header、Payload 以及 Signature 。 服务端会根据 Header、Payload、密钥再次生成一个 Signature。 拿新生成的 Signature 和 JWT 中的 Signature 作对比,如果一样就说明 Header 和 Payload 没有被修改。
JWT 安全的核心在于签名,签名安全的核心在密钥。(密钥泄漏就可能会被篡改)
4. 加强JWT安全性
-
使用安全系数高的加密算法。
-
使用成熟的开源库,没必要造轮子。
-
JWT 存放在 localStorage 中而不是 Cookie 中,避免 CSRF 风险。
-
一定不隐私信息存放在 Payload 当中。
-
密钥一定保管好,一定不要泄露出去。JWT 安全的核心在于签名,签名安全的核心在密钥。
-
Payload 要加入
exp
(JWT 的过期时间),永久有效的 JWT 不合理。并且,JWT 的过期时间不易过长。
5. 优缺点
-
无状态(自身包含了身份验证所需要的所有信息)
-
避免CSRF(使用 JWT 进行身份验证不需要依赖 Cookie)
-
适合移动端应用(兼容性)
-
单点登录友好(JWT 被保存在客户端 localStorage)
5. SSO
1. what
SSO (Single Sign On) 单点登录: 说的是用户登陆多个子系统的其中一个就有权访问与其相关的其他系统。举个例子我们在登陆了京东金融之后,我们同时也成功登陆京东的京东超市、京东国际、京东生鲜等子系统。
-
用户角度 :用户能够做到一次登录多次使用,无需记录多套用户名和密码,省心。
-
系统管理员角度 : 管理员只需维护好一个统一的账号中心就可以了,方便。
-
新系统开发角度: 新系统开发时只需直接对接统一的账号中心即可,简化开发流程,省时。
6. OAuth2.0
一个行业的标准授权协议,主要用来授权第三方应用获取有限的权限,最终目的是为第三方应用颁发一个有时效性的令牌 Token,使得第三方应用能够通过该令牌获取相关的资源。(第三方登录、支付、开发平台)
OAuth 就是一种授权机制。数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据。系统从而产生一个短期的进入令牌(token),用来代替密码,供第三方应用使用。
简单解释
7. Java定时任务
在某个特定的时间去做某个事情,也就是定时或者延时去做某个事情,将任务的执行时间安排在未来的某个点上,以达到预期的调度效果。
1. 单机定时
Spring Task
2. 分布式定时任务
Redis 是可以用来做延时任务的,基于 Redis 实现延时任务的功能无非就下面两种方案:
-
Redis 过期事件监听
-
Redisson 内置的延时队列
MQ 大部分消息队列,例如 RocketMQ、RabbitMQ,都支持定时/延时消息。定时消息和延时消息本质其实是相同的,都是服务端根据消息设置的定时时间在某一固定时刻将消息投递给消费者消费。
不过,在使用 MQ 定时消息之前一定要看清楚其使用限制,以免不适合项目需求,例如 RocketMQ 定时时长最大值默认为 24 小时且不支持自定义修改、只支持 18 个 Level 的延时并不支持任意时间。
-
优点:可以与 Spring 集成、支持分布式、支持集群、性能不错
-
缺点:功能性较差、不灵活、需要保障消息可靠性
3. 分布式任务调度
支持任务在分布式场景下的分片和高可用。
一个分布式定时任务的执行往往涉及到下面这些角色:
-
任务:首先肯定是要执行的任务,这个任务就是具体的业务逻辑比如定时发送文章。
-
调度器:其次是调度中心,调度中心主要负责任务管理,会分配任务给执行器。
-
执行器:最后就是执行器,执行器接收调度器分派的任务并执行。
XXL-JOB、PowerJob