一、什么是认证和授权?
这两个术语通常在安全性方面相互结合使用,尤其是在获得对系统的访问权限时。两者都是非常重要的主题,通常与网络相关联,作为其服务基础架构的关键部分。然而,这两个术语在完全不同的概念上是非常不同的。虽然它们通常使用相同的工具在相同的上下文中使用,但它们彼此完全不同。
身份验证意味着确认您自己的身份,而授权意味着授予对系统的访问权限。简单来说,身份验证是验证您的身份的过程,而授权是验证您有权访问的过程。
1.1 认证
身份验证是关于验证您的凭据,如用户名/用户ID和密码,以验证您的身份。系统确定您是否就是您所说的使用凭据。在公共和专用网络中,系统通过登录密码验证用户身份。身份验证通常通过用户名和密码完成,有时与身份验证因素结合使用,后者指的是各种身份验证方式。
身份验证因素决定了系统在授予访问文件和请求银行交易之外的任何内容之前验证某人身份的各种要素。用户的身份可以通过他所知道的,他拥有的或者他是什么来确定。在安全性方面,必须至少验证两个或所有三个身份验证因素,以便授予某人访问系统的权限。
根据安全级别,身份验证因素可能与以下之一不同:
- 单因素 身份验证 - 这是最简单的身份验证方法,通常依赖于简单的密码来授予用户对特定系统(如网站或网络)的访问权限。此人可以仅使用其中一个凭据请求访问系统以验证其身份。单因素身份验证的最常见示例是登录凭据,其仅需要针对用户名的密码。
- 双因素 身份验证 - 顾名思义,它是一个两步验证过程,不仅需要用户名和密码,还需要用户知道的东西,以确保更高级别的安全性。使用用户名和密码以及额外的机密信息,欺诈者几乎不可能窃取有价值的数据。
- 多重 身份验证 - 这是最先进的身份验证方法,它使用来自独立身份验证类别的两个或更多级别的安全性来授予用户对系统的访问权限。所有因素应相互独立,以消除系统中的任何漏洞。金融机构,银行和执法机构使用多因素身份验证来保护其数据和应用程序免受潜在威胁。
1.2 授权
授权发生在系统成功验证您的身份后,最终会授予您访问资源(如信息,文件,数据库,资金,位置,几乎任何内容)的完全权限。简单来说,授权决定了您访问系统的能力以及达到的程度。验证成功后,系统验证您的身份后,即可授权您访问系统资源。
授权是确定经过身份验证的用户是否可以访问特定资源的过程。它验证您是否有权授予您访问信息,数据库,文件等资源的权限。授权通常在验证后确认您的权限。简单来说,就像给予某人官方许可做某事或任何事情。
例如,验证和确认组织中的员工ID和密码的过程称为身份验证,但确定哪个员工可以访问哪个楼层称为授权。假设您正在旅行而且即将登机。当您在登记前出示机票和一些身份证明时,您会收到一张登机牌,证明机场管理局已对您的身份进行了身份验证。乘务员必须授权您登上您应该乘坐的航班,让您可以进入飞机内部及其资源。
对系统的访问受身份验证和授权的保护。可以通过输入有效凭证来验证访问系统的任何尝试,但只有在成功授权后才能接受。如果尝试已通过身份验证但未获得授权,系统将拒绝访问系统。二、RBAC权限管理模型
2.1 RBAC模型是什么?
RBAC(Role-Based Access Control)是一套成熟的权限模型。在传统权限模型中,我们直接把权限赋予用户。而在RBAC中,增加了“角色”的概念,我们首先把权限赋予角色,再把角色赋予用户。这样,由于增加了角色,授权会更加灵活方便。在RBAC中,根据权限的复杂程度,又可分为RBAC0、RBAC1、RBAC2、RBAC3。其中,RBAC0是基础,RBAC1、RBAC2、RBAC3都是以RBAC0为基础的升级。我们可以根据自家产品权限的复杂程度,选取适合的权限模型。2.2 基本模型RBAC0
RBAC0是基础,很多产品只需基于RBAC0就可以搭建权限模型了。在这个模型中,我们把权限赋予角色,再把角色赋予用户。用户和角色,角色和权限都是多对多的关系。用户拥有的权限等于他所有的角色持有权限之和。
举例:
譬如我们做一款企业管理产品,如果按传统权限模型,给每一个用户赋予权限则会非常麻烦,并且做不到批量修改用户权限。这时候,可以抽象出几个角色,譬如销售经理、财务经理、市场经理等,然后把权限分配给这些角色,再把角色赋予用户。这样无论是分配权限还是以后的修改权限,只需要修改用户和角色的关系,或角色和权限的关系即可,更加灵活方便。此外,如果一个用户有多个角色,譬如王先生既负责销售部也负责市场部,那么可以给王先生赋予两个角色,即销售经理和市场经理,这样他就拥有这两个角色的所有权限。2.3 角色分层模型RBAC1
RBAC1建立在RBAC0基础之上,在角色中引入了继承的概念。简单理解就是,给角色可以分成几个等级,每个等级权限不同,从而实现更细粒度的权限管理。
举例:
基于之前RBAC0的例子,我们又发现一个公司的销售经理可能是分几个等级的,譬如除了销售经理,还有销售副经理,而销售副经理只有销售经理的部分权限。这时候,我们就可以采用RBAC1的分级模型,把销售经理这个角色分成多个等级,给销售副经理赋予较低的等级即可。2.4 角色限制模型RBAC2
RBAC2同样建立在RBAC0基础之上,仅是对用户、角色和权限三者之间增加了一些限制。这些限制可以分成两类,即静态职责分离SSD(Static Separation of Duty)和动态职责分离DSD(Dynamic Separation of Duty)。具体限制如下图:
举例:
还是基于之前RBAC0的例子,我们又发现有些角色之间是需要互斥的,譬如给一个用户分配了销售经理的角色,就不能给他再赋予财务经理的角色了,否则他即可以录入合同又能自己审核合同;再譬如,有些公司对角色的升级十分看重,一个销售员要想升级到销售经理,必须先升级到销售主管,这时候就要采用先决条件限制了。2.5 统一模型RBAC3
RBAC3是RBAC1和RBAC2的合集,所以RBAC3既有角色分层,也包括可以增加各种限制。
举例:
这个就不举例了,统一模型RBAC3可以解决上面三个例子的所有问题。当然,只有在系统对权限要求非常复杂时,才考虑使用此权限模型。2.6 基于RBAC的延展—用户组
基于RBAC模型,还可以适当延展,使其更适合我们的产品。譬如增加用户组概念,直接给用户组分配角色,再把用户加入用户组。这样用户除了拥有自身的权限外,还拥有了所属用户组的所有权限。
举例:
譬如,我们可以把一个部门看成一个用户组,如销售部,财务部,再给这个部门直接赋予角色,使部门拥有部门权限,这样这个部门的所有用户都有了部门权限。用户组概念可以更方便的给群体用户授权,且不影响用户本来就拥有的角色权限。三、什么是Cookie?Cookie的作用是什么?
3.1 Cookie分类
Cookie 保存在客户端中,按在客户端中的存储位置,可分为内存 Cookie 和硬盘 Cookie。
内存 Cookie 由浏览器维护,保存在内存中,浏览器关闭即消失,存在时间短暂。硬盘 Cookie 保存在硬盘里,有过期时间,除非用户手动清理或到了过期时间,硬盘 Cookie 不会清除,存在时间较长。所以,按存在时间,可分为非持久 Cookie 和持久 Cookie。3.2 Cookie用途
因为 HTTP 协议是无状态的,即服务器不知道用户上一次做了什么,这严重阻碍了交互式 Web 应用程序的实现。在典型的网上购物场景中,用户浏览了几个页面,买了一盒饼干和两瓶饮料。最后结帐时,由于 HTTP 的无状态性,不通过额外的手段,服务器并不知道用户到底买了什么,所以 Cookie 就是用来绕开 HTTP 的无状态性的“额外手段”之一。服务器可以设置或读取 Cookies 中包含的信息,借此维护用户跟服务器会话)中的状态。
在刚才的购物场景中,当用户选购了第一项商品,服务器在向用户发送网页的同时,还发送了一段 Cookie,记录着那项商品的信息。当用户访问另一个页面,浏览器会把 Cookie 发送给服务器,于是服务器知道他之前选购了什么。用户继续选购饮料,服务器就在原来那段 Cookie 里追加新的商品信息。结帐时,服务器读取发送来的 Cookie 即可。
Cookie 另一个典型的应用是当登录一个网站时,网站往往会请求用户输入用户名和密码,并且用户可以勾选“下次自动登录”。如果勾选了,那么下次访问同一网站时,用户会发现没输入用户名和密码就已经登录了。这正是因为前一次登录时,服务器发送了包含登录凭据(用户名加密码的某种加密形式)的 Cookie 到用户的硬盘上。第二次登录时,如果该 Cookie 尚未到期,浏览器会发送该 Cookie,服务器验证凭据,于是不必输入用户名和密码就让用户登录了。F12进入开发者模式,在console中输入document.cookie命令即可查看Cookie信息
3.3 Cookie缺陷
- Cookie 会被附加在每个 HTTP 请求中,所以无形中增加了流量。
- 由于 HTTP 请求中的 Cookie 是明文传递的,所以安全性成问题,除非使用超文本传输安全协定。
Cookie 的大小限制在 4 KB 左右,对于复杂的存储需求来说是不够用的。
四、Cookie和Session有什么区别?
cookie数据存放在客户的浏览器上,session数据放在服务器上.
简单的说,当你登录一个网站的时候,如果web服务器端使用的是session,那么所有的数据都保存在服务器上面,客户端每次请求服务器的时候会发送当前会话的session_id,服务器根据当前session_id判断相应的用户数据标志,以确定用户是否登录,或具有某种权限。
由于数据是存储在服务器上面,所以你不能伪造,但是如果你能够获取某个登录用户的session_id,用特殊的浏览器伪造该用户的请求也是能够成功的。session_id是服务器和客户端链接时候随机分配的,一般来说是不会有重复,但如果有大量的并发请求,也不是没有重复的可能性。
Session是由应用服务器维持的一个服务器端的存储空间,用户在连接服务器时,会由服务器生成一个唯一的SessionID,用该SessionID 为标识符来存取服务器端的Session存储空间。而SessionID这一数据则是保存到客户端,用Cookie保存的,用户提交页面时,会将这一 SessionID提交到服务器端,来存取Session数据。这一过程,是不用开发人员干预的。所以一旦客户端禁用Cookie,那么Session也会失效。
- cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗考虑到安全应当使用session。
- 设置cookie时间可以使cookie过期。但是使用session-destory(),我们将会销毁会话。
- **
- 单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。(Session对象没有对存储的数据量的限制,其中可以保存更为复杂的数据类型)
注意:
- session很容易失效,用户体验很差;
- 虽然cookie不安全,但是可以加密 ;
- cookie也分为永久和暂时存在的;
- 浏览器有禁止cookie功能,但一般用户都不会设置;
- 一定要设置失效时间,要不然浏览器关闭就消失了;
两者最大的区别在于生存周期,一个是IE启动到IE关闭。(浏览器页面一关,session就消失了),一个是预先设置的生存周期,或永久的保存于本地的文件。(cookie)
五、如何使用Session-Cookie方案进行身份验证?
很多时候我们都是通过 SessionID 来实现特定的用户,SessionID 一般会选择存放在 Redis 中。举个例子:
- 用户成功登陆系统,然后返回给客户端具有 SessionID 的 Cookie
- 当用户向后端发起请求的时候会把 SessionID 带上,这样后端就知道你的身份状态了。
关于这种认证方式更详细的过程如下:
- 用户向服务器发送用户名、密码、验证码用于登陆系统。
- 服务器验证通过后,服务器为用户创建一个 Session,并将 Session 信息存储起来。
- 服务器向用户返回一个 SessionID,写入用户的 Cookie。
- 当用户保持登录状态时,Cookie 将与每个后续请求一起被发送出去。
- 服务器可以将存储在 Cookie 上的 SessionID 与存储在内存中或者数据库中的 Session 信息进行比较,以验证用户的身份,返回给用户客户端响应信息的时候会附带用户当前的状态。
使用 Session 的时候需要注意下面几个点:
- 依赖 Session 的关键业务一定要确保客户端开启了 Cookie。
-
六、多服务器节点下Session-Cookie方案如何做?
Session-Cookie方案在单体环境是一个非常好的身份认证方案。但是,当服务器水平拓展成多节点时,Session-Cookie 方案就要面临挑战了。
举个例子:假如我们部署了两份相同的服务 A、B,用户第一次登陆的时候 ,Nginx 通过负载均衡机制将用户请求转发到 A 服务器,此时用户的 Session 信息保存在 A 服务器。结果,用户第二次访问的时候 Nginx 将请求路由到 B 服务器,由于 B 服务器没有保存用户的 Session 信息,导致用户需要重新进行登陆。我们应该如何避免上面这种情况的出现呢?
有几个方案可供参考: 某个用户的所有请求都通过特性的哈希策略分配给同一个服务器处理。这样的话,每个服务器都保存了一部分用户的 Session 信息。服务器宕机,其保存的所有 Session 信息就完全丢失了。
- 每一个服务器保存的 Session 信息都是互相同步的,也就是说每一个服务器都保存了全量的 Session 信息。每当一个服务器的 Session 信息发生变化,我们就将其同步到其他服务器。这种方案成本太大,并且,节点越多时,同步成本也越高。
- 单独使用一个所有服务器都能访问到的数据节点(比如缓存)来存放 Session 信息。为了保证高可用,数据节点尽量要避免是单点。
七、如果没有Cookie的话Session还能使用吗?
一般是通过 Cookie 来保存 SessionID ,假如你使用了 Cookie 保存 SessionID 的方案的话, 如果客户端禁用了 Cookie,那么 Session 就无法正常工作。
但是,并不是没有 Cookie 之后就不能用 Session 了,比如你可以将 SessionID 放在请求的 url 里面:https://javaguide.cn/?Session_id=xxx 。这种方案的话可行,但是安全性和用户体验感降低。当然,为了你也可以对 SessionID 进行一次加密之后再传入后端。八、为什么Cookie无法防止CSRF攻击,而Token可以?
CSRF(Cross Site Request Forgery)一般被翻译为 跨站请求伪造 。那么什么是 跨站请求伪造 呢?说简单用你的身份去发送一些对你不友好的请求。举个简单的例子:
小壮登录了某网上银行,他来到了网上银行的帖子区,看到一个帖子下面有一个链接写着“科学理财,年盈利率过万”,小壮好奇的点开了这个链接,结果发现自己的账户少了 10000 元。这是这么回事呢?原来黑客在链接中藏了一个请求,这个请求直接利用小壮的身份给银行发送了一个转账请求,也就是通过你的 Cookie 向银行发出请求。
上面也提到过,进行 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?什么是JWT?
Session 信息需要保存一份在服务器端。这种方式会带来一些麻烦,比如需要我们保证保存 Session 信息服务器的可用性、不适合移动端(依赖 Cookie)等等。
有没有一种不需要自己存放 Session 信息就能实现身份验证的方式呢?使用 Token 即可!Token是服务端按照一定规则生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。
JWT (JSON Web Token) 就是这种方式的实现,通过这种方式服务器端就不需要保存 Session 数据了,只用在客户端保存服务端返回给客户的 Token 就可以了,扩展性得到提升。
JWT 本质上就一段签名的 JSON 格式的数据。由于它是带有签名的,因此接收者便可以验证它的真实性。
JWT 由 3 部分构成:
Header:头信息,描述 JWT 的元数据,定义了生成签名的算法以及 Token 的类型。通常如下所示:
{
"alg": "HS256",
"typ": "JWT"
}
在上面的代码中,alg属性表示签名使用的算法,默认为HMAC SHA256(写为HS256);typ属性表示令牌的类型,JWT令牌统一写为JWT。最后,使用Base64 URL算法将上述JSON对象转换为字符串保存。
Payload:有效载荷,用来存放实际需要传递的数据, 是JWT的主体内容部分,也是一个JSON对象,包含需要传递的数据。 JWT指定七个默认 字段供选择:
iss:发行人
exp:到期时间
sub:主题
aud:用户
nbf:在此之前不可用
iat:发布时间
jti:JWT ID用于标识该JWT
除以上默认字段外,我们还可以自定义私有字段,如下例:
{
"sub": "1234567890",
"name": "Helen",
"admin": true
}
请注意,默认情况下JWT是未加密的,任何人都可以解读其内容,因此不要构建隐私信息字段,存放保密信息,以防止信息泄露。JSON对象也使用Base64 URL算法转换为字符串保存。
Signature(签名):服务器通过Payload、Header和一个密钥(secret)使用 Header 里面指定的签名算法(默认是 HMAC SHA256)生成,起防伪作用。
JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted. ——JSON Web Token (JWT)
🙇♂️JWT问题和趋势:
- JWT不仅可用于认证,还可用于信息交换。善用JWT有助于减少服务器请求数据库的次数。
- 生产的token可以包含基本信息,比如id、用户昵称、头像等信息,避免再次查库
- 存储在客户端,不占用服务端的内存资源
- JWT默认不加密,但可以加密。生成原始令牌后,可以再次对其进行加密。
- 当JWT未加密时,一些私密数据无法通过JWT传输。
- JWT的最大缺点是服务器不保存会话状态,所以在使用期间不可能取消令牌或更改令牌的权限。也就是说,一旦JWT签发,在有效期内将会一直有效。
- JWT本身包含认证信息,token是经过base64编码,所以可以解码,因此token加密前的对象不应该包含敏感信息,一旦信息泄露,任何人都可以获得令牌的所有权限。为了减少盗用,JWT的有效期不宜设置太长。对于某些重要操作,用户在使用时应该每次都进行进行身份验证。
- 为了减少盗用和窃取,JWT不建议使用HTTP协议来传输代码,而是使用加密的HTTPS协议进行传输。
十、如何基于Token进行身份验证?
在基于 Token 进行身份验证的的应用程序中,服务器通过Payload、Header和一个密钥(secret)创建令牌(Token)并将 Token 发送给客户端,客户端将 Token 保存在 Cookie 或者 localStorage 里面,以后客户端发出的所有请求都会携带这个令牌。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP Header 的 Authorization 字段中:Authorization: Bearer Token。