认证鉴权
认证鉴权
认证 (Authentication) 和授权 (Authorization)的区别是什么?
这是一个绝大多数人都会混淆的问题。首先先从读音上来认识这两个名词,很多人都会把它俩的读音搞混,所以我建议你先先去查一查这两个单词到底该怎么读,他们的具体含义是什么。
说简单点就是:
- 认证 (Authentication): 你是谁。
- 授权 (Authorization): 你有权限干什么。
Authentication(认证) 是验证您的身份的凭据(例如用户名/用户 ID 和密码),通过这个凭据,系统得以知道你就是你,也就是说系统存在你这个用户。所以,Authentication 被称为身份/用户验证。
Authorization(授权) 发生在 Authentication(认证) 之后。授权嘛,光看意思大家应该就明白,它主要掌管我们访问系统的权限。比如有些特定资源只能具有特定权限的人才能访问比如 admin,有些对系统资源操作比如删除、添加、更新只能特定人才具有。
RBAC 模型
系统权限控制最常采用的访问控制模型就是 RBAC 模型 。
什么是 RBAC 呢? RBAC 即基于角色的权限访问控制(Role-Based Access Control)。这是一种通过角色关联权限,角色同时又关联用户的授权的方式。
简单地说:一个用户可以拥有若干角色,每一个角色又可以被分配若干权限,这样就构造成“用户-角色-权限” 的授权模型。在这种模型中,用户与角色、角色与权限之间构成了多对多的关系。
在 RBAC 权限模型中,权限与角色相关联,用户通过成为包含特定角色的成员而得到这些角色的权限,这就极大地简化了权限的管理。
为了实现 RBAC 权限模型,数据库表的常见设计如下(一共 5 张表,2 张用户建立表之间的联系):

通过这个权限模型,我们可以创建不同的角色并为不同的角色分配不同的权限范围(菜单)。

通常来说,如果系统对于权限控制要求比较严格的话,一般都会选择使用 RBAC 模型来做权限控制。
Session和Cookies的区别
Cookies
- 浏览器端第一次发送请求到服务器端
- 服务器端创建Cookie,该Cookie中包含用户的信息,然后将该Cookie发送到浏览器端
- 浏览器端再次访问服务器端时会携带服务器端创建的Cookie
- 服务器端通过Cookie中携带的数据区分不同的用户

Cookies通常用于存储少量的文本数据,比如用户的偏好设置、登录状态等。cookie 有存储大小限制,4KB 左右。
浏览器每次请求会携带 cookie 在请求头中。
字符编码为 Unicode,不支持直接存储中文。
Cookies相对不太安全,因为它们存储在用户的计算机上,可能会被恶意程序或者其他网站访问。
cookie 不可跨域,但是在如果设置了 domain,那么它们是可以在一级域名和二级域名之间共享的
Session
session 由服务端创建,当一个请求发送到服务端时,服务器会检索该请求里面有没有包含 sessionId 标识,如果包含了 sessionId,则代表服务端已经和客户端创建过 session,然后就通过这个 sessionId 去查找真正的 session,如果没找到,则为客户端创建一个新的 session,并生成一个新的 sessionId 与 session 对应,然后在响应的时候将 sessionId 给客户端,通常是存储在 cookie 中。如果在请求中找到了真正的 session,验证通过,正常处理该请求。

优点
- session 比 cookie 更加安全,因为它是存在服务端的
- cookie 只支持存储字符串数据,session 可以存储任意类型数据(如对象)
缺点
cookie 的有效期可以设置较长时间,session 有效期都比较短
session 存储空间很大,但如果并发量很高,会比较占用服务器资源
在集群部署的环境下需要考虑不同服务器的session的共享
如何使用 Session-Cookie 方案进行身份验证?
很多时候我们都是通过 SessionID
来实现特定的用户,SessionID
一般会选择存放在 Redis 中。举个例子:
- 用户成功登陆系统,然后返回给客户端具有
SessionID
的Cookie
。 - 当用户向后端发起请求的时候会把
SessionID
带上,这样后端就知道你的身份状态了。

用户向服务器发送用户名、密码、验证码用于登陆系统。
服务器验证通过后,服务器为用户创建一个 Session
,并将 Session
信息存储起来。
服务器向用户返回一个 SessionID
,写入用户的 Cookie
。
当用户保持登录状态时,Cookie
将与每个后续请求一起被发送出去。
服务器可以将存储在 Cookie
上的 SessionID
与存储在内存中或者数据库中的 Session
信息进行比较,以验证用户的身份,返回给用户客户端响应信息的时候会附带用户当前的状态。
使用 Session
的时候需要注意下面几个点:
- 依赖
Session
的关键业务一定要确保客户端开启了Cookie
。 - 注意
Session
的过期时间。
另外,Spring Session 提供了一种跨多个应用程序或实例管理用户会话信息的机制。如果想详细了解可以查看下面几篇很不错的文章:
- Getting Started with Spring Sessionopen in new window
- Guide to Spring Sessionopen in new window
- Sticky Sessions with Spring Session & Redis
如果没有 Cookie 的话 Session 还能用吗?
一般是通过 Cookie
来保存 SessionID
,假如你使用了 Cookie
保存 SessionID
的方案的话, 如果客户端禁用了 Cookie
,那么 Session
就无法正常工作。
但是,并不是没有 Cookie
之后就不能用 Session
了,比如你可以将 SessionID
放在请求的 url
里面https://PALE13.github.com/?Session_id=xxx
。这种方案的话可行,但是安全性和用户体验感降低。当然,为了安全你也可以对 SessionID
进行一次加密之后再传入后端。
多服务器节点下 Session-Cookie 方案(Session共享问题)
Session-Cookie 方案在单体环境是一个非常好的身份认证方案。但是,当服务器水平拓展成多节点时,Session-Cookie 方案就要面临挑战了。
举个例子:假如我们部署了两份相同的服务 A,B,用户第一次登陆的时候 ,Nginx 通过负载均衡机制将用户请求转发到 A 服务器,此时用户的 Session 信息保存在 A 服务器。结果,用户第二次访问的时候 Nginx 将请求路由到 B 服务器,由于 B 服务器没有保存 用户的 Session 信息,导致用户需要重新进行登陆。
我们应该如何避免上面这种情况的出现呢?
有几个方案可供大家参考:
- 某个用户的所有请求都通过特性的哈希策略分配给同一个服务器处理。这样的话,每个服务器都保存了一部分用户的 Session 信息。服务器宕机,其保存的所有 Session 信息就完全丢失了。
- 每一个服务器保存的 Session 信息都是互相同步的,也就是说每一个服务器都保存了全量的 Session 信息。每当一个服务器的 Session 信息发生变化,我们就将其同步到其他服务器。这种方案成本太大,并且,节点越多时,同步成本也越高。
- 单独使用一个所有服务器都能访问到的数据节点(比如Redis)来存放 Session 信息。为了保证高可用,数据节点尽量要避免是单点。
- Spring Session 是一个用于在多个服务器之间管理会话的项目。它可以与多种后端存储(如 Redis、MongoDB 等)集成,从而实现分布式会话管理。通过 Spring Session,可以将会话数据存储在共享的外部存储中,以实现跨服务器的会话同步和共享。
Token
Token 是一种在客户端和服务端之间传递身份信息的方式。当用户登录成功后,服务端会生成一个 Token,将其发送给客户端。客户端在后续的请求中,需要将 Token 携带在请求头或请求参数中。服务端通过验证 Token 的合法性,就可以确定该请求来自哪个用户,并且可以根据用户的权限进行相应的操作。Token 可以有效地避免了 Cookie 的一些安全问题,比如 CSRF 攻击。
token的组成
Token是一个由一串字符组成的令牌,用于在计算机系统中进行身份验证和授权。它通常由三个部分组成:标头、有效载荷、签名。
- 标头(Header):包含了算法和类型,用于指定如何对有效载荷进行编码和签名。常用的算法有HMAC、RSA、SHA等。
- 有效载荷(Payload):包含了一些信息,如用户ID、角色、权限等,用于验证身份和授权。有效载荷可以是加密的,也可以是明文的。
- 签名(Signature):是对标头和有效载荷进行签名后得到的值,用于验证token的完整性和真实性。签名通常使用私钥进行签名,并使用公钥进行验证。
一个完整的token包含了标头、有效载荷和签名三个部分,它们一起构成了一个安全的令牌,用于进行身份验证和授权。
token认证流程
- 客户端发起登录请求,比如用户输入用户名和密码后登录。
- 服务端校验用户名和密码后,将用户 id 和一些其它信息进行加密,生成 token。
- 服务端将 token 响应给客户端。
- 客户端收到响应后将 token 存储下来。
- 下一次发送请求后需要将 token 携带上,比如放在请求头中或者其它地方。
- 服务端 token 后校验,校验通过则正常返回数据。
优点
安全,因为 token 一般只有用户 id,就算被截取了也没什么用。
无需消耗服务器内存资源,它相当于只存了用户 id,session 相当于存储了用户的所有信息。
跨域处理较为方便,比如多台服务器之间可以共用一个 token。
为什么 Cookie 无法防止 CSRF 攻击,而 Token 可以?
CSRF(Cross Site Request Forgery) 一般被翻译为 跨站请求伪造 。那么什么是 跨站请求伪造 呢?说简单点,就是用你的身份去发送一些对你不友好的请求。举个简单的例子:
小壮登录了某网上银行,他来到了网上银行的帖子区,看到一个帖子下面有一个链接写着“科学理财,年盈利率过万”,小壮好奇的点开了这个链接,结果发现自己的账户少了 10000 元。这是这么回事呢?原来黑客在链接中藏了一个请求,这个请求直接利用小壮的身份给银行发送了一个转账请求,也就是通过你的 Cookie 向银行发出请求
1 |
|
上面也提到过,进行 Session
认证的时候,我们一般使用 Cookie
来存储 SessionId
,当我们登陆后后端生成一个 SessionId
放在 Cookie 中返回给客户端,服务端通过 Redis 或者其他存储工具记录保存着这个 SessionId
,客户端登录以后每次请求都会带上这个 SessionId
,服务端通过这个 SessionId
来标示你这个人。如果别人通过 Cookie
拿到了 SessionId
后就可以代替你的身份访问系统了。
Session
认证中 Cookie
中的 SessionId
是由浏览器发送到服务端的,借助这个特性,攻击者就可以通过让用户误点攻击链接,达到攻击效果。
但是,我们使用 Token
的话就不会存在这个问题,在我们登录成功获得 Token
之后,一般会选择存放在 localStorage
(浏览器本地存储)中。然后我们在前端通过某些方式会给每个发到后端的请求加上这个 Token
,这样就不会出现 CSRF 漏洞的问题。因为,即使你点击了非法链接发送了请求到服务端,这个非法请求是不会携带 Token
的,所以这个请求将是非法的。

需要注意的是:不论是 Cookie
还是 Token
都无法避免 跨站脚本攻击(Cross Site Scripting)XSS 。
跨站脚本攻击(Cross Site Scripting)缩写为 CSS 但这会与层叠样式表(Cascading Style Sheets,CSS)的缩写混淆。因此,有人将跨站脚本攻击缩写为 XSS。
XSS 中攻击者会用各种方式将恶意代码注入到其他用户的页面中,就可以通过脚本盗用信息比如 Cookie
,token
密码学相关
对称加密和非对称加密原理
对称加密和非对称加密是两种常见的密码学算法,用于保护数据的机密性和安全性。它们的原理和使用方式有所不同:
对称加密(Symmetric Encryption)原理:
对称加密使用相同的密钥(称为密钥)来进行加密和解密操作。加密和解密使用相同的密钥,因此对称加密也被称为共享密钥加密。对称加密的过程如下:- 加密过程:将明文数据和密钥作为输入,通过加密算法生成密文数据。
- 解密过程:将密文数据和密钥作为输入,通过解密算法还原出明文数据。
对称加密算法的特点包括:
- 快速:对称加密算法通常运算速度快,适合处理大量数据。
- 简单:对称加密算法的加密和解密过程相对简单,计算资源要求较低。
- 密钥管理:由于密钥的共享性,对称加密在密钥管理方面存在一些挑战,如密钥的分发、存储和保护。
常见的对称加密算法有DES(Data Encryption Standard)、3DES(Triple DES)、AES(Advanced Encryption Standard)等。
非对称加密(Asymmetric Encryption)原理:
非对称加密使用一对密钥,分别是公钥和私钥。公钥用于加密数据,私钥用于解密数据。非对称加密的过程如下:- 加密过程:将明文数据和接收方的公钥作为输入,通过加密算法生成密文数据。
- 解密过程:将密文数据和接收方的私钥作为输入,通过解密算法还原出明文数据。
非对称加密算法的特点包括:
- 安全性:非对称加密算法基于数学问题,通过密钥的分离确保了更强的安全性。
- 密钥分发:非对称加密中,公钥可以公开发布,而私钥必须保密。公钥可以在任何需要加密数据的地方使用,而私钥通常只在解密数据的地方保留。
- 数字签名:非对称加密算法可以用于生成和验证数字签名,确保数据的完整性和身份认证。
常见的非对称加密算法有RSA(Rivest-Shamir-Adleman)、DSA(Digital Signature Algorithm)、ECC(Elliptic Curve Cryptography)等。
对称加密和非对称加密算法通常结合使用。对称加密用于加密数据本身,而非对称加密用于确保密钥的安全性和进行身份验证。通常,在加密通信中,对称加密用于加密数据,而非对称加密用于安全地交换对称加密所需的密钥。这样,即保证了数据的机密性,又确保了密钥的安全性。
解释一下数字签名和数字信封
数字签名:(发送方私钥签名,公钥解密)
数字签名是一种用于验证消息来源和完整性的密码学机制。它使用私钥对消息进行签名,然后其他人可以使用公钥来验证签名的有效性。数字签名提供了以下保证:
身份验证:接收方可以验证发送方的身份,确认消息确实来自发送方。
完整性:接收方可以验证消息在传输过程中是否被篡改。
非否认性:发送方不能否认签署过的消息,因为签名是使用其私钥生成的,只有发送方的私钥可以生成有效的签名。
数字信封:(接收方的公钥加密,私钥解密)
数字信封是一种使用非对称加密技术来传输对称密钥的机制。它用于在不安全的通信信道上安全地传输对称密钥,以便进行后续的对称加密通信。数字信封的过程如下:
发送方生成一个随机的对称密钥(会话密钥)用于加密数据。
发送方使用接收方的公钥进行加密,将会话密钥加密后的密文一起发送给接收方。
接收方使用自己的私钥进行解密,获取会话密钥。
接收方使用会话密钥对接收到的数据进行加密和解密。
数字信封的主要目的是在不安全的通信信道上安全地传输对称密钥,以便确保对称加密过程的安全性。它结合了非对称加密和对称加密的优势:非对称加密提供了密钥交换的安全性,而对称加密提供了高效的加密和解密过程。
总结来说,数字签名用于验证消息的完整性和身份,而数字信封用于安全地传输对称密钥。这两种机制在保护数据的安全性和真实性方面发挥着重要作用。
数字签名如何验证消息的完整性
数字签名通过使用私钥对消息进行签名,然后使用公钥来验证签名的有效性,从而实现对消息完整性的验证。下面是数字签名验证消息完整性的基本过程:
- 发送方签名:
- 使用哈希函数(如SHA-256)对原始消息进行哈希计算,生成消息的摘要(哈希值)。
- 然后使用发送方的私钥对摘要进行加密,生成数字签名签名过程使用特定的签名算法,例如RSA、DSA或ECDSA。
- 接收方验证:
- 接收方使用发送方的公钥获取数字签名和原始消息。
- 接收方使用相同的哈希函数对原始消息进行哈希,生成消息摘要。
- 接收方使用发送方的公钥对数字签名进行解密,得到解密后的摘要。
- 比较和验证:
- 接收方将接收到的解密后的摘要与自己计算的消息摘要进行比较。
- 如果两个摘要相同,说明消息没有被篡改,验证通过。
- 如果两个摘要不同,说明消息被篡改或签名无效,验证失败。
通过这个过程,接收方可以验证消息的完整性。如果接收到的解密后的摘要与自己计算的消息摘要相匹配,那么可以确定消息没有被篡改。这是因为只有发送方的私钥可以生成有效的签名,而接收方使用发送方的公钥来验证签名的有效性。
需要注意的是,数字签名只能验证消息的完整性,而无法保证消息的机密性。为了同时实现机密性和完整性,可以将数字签名与对称加密结合使用,以实现加密、完整性验证和身份验证的综合保护。
数字签名和数字证书有什么区别
数字签名和数字证书都是公钥基础设施(PKI)中的重要组成部分,但它们有不同的作用和应用。
数字签名(Digital Signature):
- 作用:
- 数字签名用于验证消息或文档的真实性和完整性。发送者使用自己的私钥对消息进行签名,接收者使用发送者的公钥来验证签名,从而确保消息的来源和完整性。(问题:如何保证该)
- 工作原理:
- 发送者使用哈希函数对消息生成摘要,然后使用自己的私钥对摘要进行加密生成数字签名。接收者使用发送者的公钥解密数字签名得到摘要,再对接收到的消息进行哈希,比对两个摘要,如果一致,则验证通过。
- 应用场景:
- 数字签名广泛应用于数据完整性验证、身份认证、电子文件签名等场景。常见的数字签名算法有RSA、DSA、ECDSA等。
数字证书(Digital Certificate):
- 作用:
- 数字证书用于验证公钥的真实性,它包含了用户的公钥以及与该公钥相关的其他信息,并由数字签名保护。数字证书的主要作用是提供一种机制,确保公钥属于特定的实体(如个人、组织或服务器)。
- 工作原理:
- 数字证书包含了持有者的公钥、持有者的信息以及CA的数字签名。数字签名由证书颁发机构(Certificate Authority,CA)使用自己的私钥生成,其他用户使用CA的公钥验证数字签名,从而确保证书的真实性。(CA的数字签名是为了确保数字证书的真实性)
- 应用场景:
- 数字证书广泛应用于建立安全通信通道,例如在HTTPS中,服务器使用数字证书来证明自己的身份,并为客户端提供公钥,以确保通信的机密性和完整性。
在实际使用中,数字签名和数字证书通常是结合使用的,数字证书用于证明公钥的真实性,数字签名用于验证消息或文档的完整性。CA(证书颁发机构)是数字证书的重要组成部分,负责签发和管理数字证书,同时也为数字签名提供信任链。
对比:CA的角色在数字签名认证中是颁发数字证书,证明用户的身份和公钥的有效性。数字证书中包含了用户的公钥和相关信息,并由CA对其进行数字签名。
用户不能直接把自己的公钥公开吗,为什么还需要CA?
用户可以选择将自己的公钥公开,这样其他人就可以使用该公钥来验证用户的数字签名。然而,为了确保公钥的真实性和可信性,以及对用户身份进行验证,使用CA是非常有益的。
以下是使用CA的一些原因:
- 可信任的第三方验证:CA是一个可信任的第三方机构,它有权威地验证用户的身份信息。通过与CA建立信任关系,其他人可以相信该CA已经对用户进行了适当的身份验证。
- 数字证书的信任链:CA在数字证书中对用户的公钥进行数字签名,形成了一个信任链。其他人可以验证数字证书的签名,以确保公钥的真实性和完整性。这样,即使其他人没有直接访问用户的公钥,他们仍然可以信任数字证书的有效性。
- 抵御中间人攻击:使用CA颁发的数字证书可以防止中间人攻击。中间人攻击是指攻击者冒充用户或CA与其他人进行通信,而其他人无法确定其真实身份。通过验证数字证书中的签名,其他人可以确保通信双方的身份是可信的,从而防止中间人攻击。
- 维护公钥的变更与撤销:如果用户的公钥发生变化或需要撤销,CA可以更新或吊销数字证书。这样,其他人可以通过检查数字证书的状态来确保使用的公钥是最新和有效的。
###解释一下单向加密的原理,有哪些技术使用了单向加密
单向加密(One-way encryption)是一种加密技术,其主要特点是加密过程是不可逆的,即无法通过密文还原为原始明文。它的核心原理是应用哈希函数对输入数据进行转换,生成固定长度的哈希值,也称为摘要(Digest)。
以下是单向加密的基本原理:
输入数据:单向加密算法接收输入数据,可以是任意长度的二进制数据,如密码、文本等。
哈希函数:单向加密算法使用哈希函数对输入数据进行转换,生成固定长度的哈希值。哈希函数的设计使得即使输入数据发生微小的变化,哈希值也会发生巨大的变化。
哈希值输出:单向加密算法的输出结果是哈希值或摘要。
哈希值通常是一个固定长度的二进制字符串,表示输入数据的唯一标识。由于单向加密是不可逆的,即无法从哈希值还原为原始数据,所以它主要用于验证数据的完整性和身份验证,而不是用于加密和解密敏感信息。常见的单向加密算法包括MD5、SHA-1、SHA-256等。
单向加密技术应用广泛,以下是一些使用了单向加密的技术:
密码存储:在存储用户密码时,通常将密码进行单向加密并存储其哈希值。当用户登录时,输入的密码经过相同的单向加密算法,与存储的哈希值进行比较,以验证密码的正确性。
数字证书:数字证书使用单向加密来生成证书的数字指纹,也称为证书摘要。这个数字指纹用于验证证书的完整性和真实性。
数据完整性验证:单向加密可用于验证数据在传输过程中是否被篡改。发送方可以对数据进行单向加密,然后将数据和对应的哈希值一起发送给接收方。接收方对接收到的数据进行单向加密,并将生成的哈希值与发送方提供的哈希值进行比较,以验证数据的完整性。
消息认证码(MAC):MAC算法使用单向加密来生成消息的完整性校验码,用于验证消息的完整性和真实性。