数据脱敏
随着互联网的发展,Web应用的规模也在不断的扩大,系统架构也在不断的演进。
单系统已经发展成为了多系统组成的应用群,单点登录的出现,可以让用户更便捷的管理自己的账户,用户只需操作一次登录或者注销便能完成对所有系统的统一操作。
在 Web 开发中,我们经常会遇到各种各样的认证机制的概念和名词,如SSO(Single Sign-On)、Cookies、Session、Token 和 OAuth 2.0 等,下面详细解释一下它们之间的联系与异同。
SSO 是一种一次登录后通过 token 访问多个业务的机制。用户只需要在一个系统中登录一次,就可以在其他多个系统中自由访问,无需再次登录,大大提高了用户体验。
例如,Google 的各种服务(如 Gmail、Google Drive、Google Photos 等)就使用了 SSO。用户只需要登录一次 Google 账号,就可以访问 Google 的所有服务。
Cookies 是一种用于服务器与浏览器交换数据的方式。当服务器响应时,它会通过 Set-Cookie 的 HTTP header 写入浏览器。然后,浏览器在每次请求时会自动在 header 中带上 cookies。当我们设置 cookie 时,可以设置过期时间、域名、路径、HttpOnly 等条件,只有满足这些条件的请求才会带上该 cookie。
例如,当用户登录一个网站后,服务器可以设置一个包含用户 ID 的 cookie,然后浏览器在后续的每次请求中都会带上这个 cookie,服务器就可以通过这个 cookie 来识别用户。
HTTP Cookie(也叫 Web Cookie或浏览器 Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。通常,它用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态。Cookie 使基于无状态的 HTTP 协议记录稳定的状态信息成为了可能。
Cookie 主要用于以下三个方面:
由于 HTTP 请求是无状态的,如果我们需要在多次请求中保持用户状态,就需要额外的数据。这个数据可以是一个随机的字符串(Session ID),这样带有同样 Session ID 的请求就可以被关联为同一个会话。Session ID 的交互可以用 set cookie 的方式实现。
例如,当用户登录一个网站后,服务器可以生成一个 Session ID 并通过 cookie 发送给浏览器,然后浏览器在后续的每次请求中都会带上这个 Session ID,服务器就可以通过这个 Session ID 来识别用户。
Session 代表着服务器和客户端一次会话的过程。Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当客户端关闭会话,或者 Session 超时失效时会话结束。
Token 是客户端发送请求时携带的凭证,用于表明自己的身份(Authentication)。常见的 tokens 有两种:
例如,当用户登录一个网站后,服务器可以生成一个 JWT token,并将其发送给浏览器。然后浏览器在后续的每次请求中都会带上这个 JWT token,服务器就可以通过这个 JWT token 来识别用户。
OAuth 2.0 是一种授权机制。当用户在访问 A 应用时需要使用 B 应用的数据,用户可以通过获取 B 应用的授权 token,然后授权给 A 应用使用该 token 获取 B 应用的数据。
例如,用户在使用一个日历应用时,可能需要访问他在 Google 日历上的数据。这时,用户可以通过 OAuth 2.0 获取 Google 日历的授权 token,然后将这个 token 授权给日历应用,日历应用就可以使用这个 token 来获取 Google 日历的数据。
Cookie 和 Session 有什么不同?
Cookies 和 Session 都是用于在无状态的 HTTP 请求中保存状态信息的机制。但它们的工作方式有所不同。
Cookies 是存储在客户端(浏览器)的小段数据,服务器可以通过 Set-Cookie HTTP header 将数据写入 Cookies。而 Session 是存储在服务器端的数据,它通过在 Cookies 中保存一个 Session ID 来关联客户端和服务器端的数据。
因此,Cookies 的主要问题是容量有限(每个域名下最多只能存储 20 个 Cookies,每个 Cookie 大小不能超过 4KB),而 Session 的主要问题是如果用户数量过多,会占用大量服务器资源。
Token 和 Cookies/Session 都是用于认证用户身份的机制。但它们的工作方式有所不同。
Cookies/Session 是通过在服务器端保存用户状态信息来实现认证的,而 Token(如 JWT)则是无状态的,它将用户状态信息加密后直接存储在 Token 中,服务器不需要保存任何用户状态信息。
因此,Token 的主要优点是可以跨域(Cookies 在跨域场景下有很多限制),并且服务器不需要保存状态信息,可以轻松实现水平扩展。
SSO(Single Sign-On)是一种允许用户在多个应用之间共享认证状态的机制,它通常基于 Cookies/Session 或 Token 实现。
与 Cookies/Session/Token 只能在单个应用中保存用户状态不同,SSO 允许用户在多个应用之间共享认证状态,用户只需要登录一次,就可以访问所有连接的应用。
OAuth 2.0 是一种授权机制,它允许用户将他们在一个应用中的权限(如访问数据的权限)授权给另一个应用。
这是一种最古老的安全认证方式,这种方式就是简单的访问API的时候,带上访问的username和password,由于信息会暴露出去,所以现在也越来越少用了,现在都用更加安全保密的认证方式,可能某些老的平台还在用。
为了解决HTTP无状态的问题,Lou等在1994年的时候,推出了Cookie。
Cookie是服务端发送给客户端的一段特殊信息,这些信息以文本的方式存放在客户端,客户端每次向服务端发送请求时都会带上这些特殊信息。
有了Cookie之后,服务端就可以获取到客户端传递过来的信息,若是需要对信息进行验证,还需要经过Session。
客户端请求服务端,服务端会为此次请求开辟一块内存区域,这就是Session对象。
流程简述
Cookie+Session 认证机制,就是为一次请求认证在服务端创建一个Session对象,同时在客户端的浏览器端创建了一个Cookie对象;通过客户端携带Cookie对象来与服务器端的session对象匹配来实现状态管理的。默认的,当我们关闭浏览器的时候,cookie会被删除。但可以通过修改cookie 的expire time使cookie在一定时间内有效;
应用场景
Cookie+Session的登录方式是最经典的一种登录方式,如今仍有大量企业在用。
服务端的SessionId可能存放在不少地方,如内存、文件、数据库等。
第一次登录完成之后,后续的访问就能够直接使用Cookie进行身份验证了:
用户访问a.com/page页面时,会自动带上第一次登录时写入的Cookie。
服务端对比Cookie中的SessionId和保存在服务端的SessionId是否一致。
若是一致,则身份验证成功。
CSRF攻击是一种利用用户在目标网站上已认证的会话执行非预期操作的攻击方式。攻击者通过欺骗用户使其在受信任的网站上执行恶意操作,如转账、修改账户信息等。常见的CSRF攻击方式,如下:
1、直接链接方式,攻击者通过诱使用户点击恶意链接,向目标网站发送伪造请求。当用户点击链接时,浏览器会自动发送包含用户认证信息的请求,从而执行攻击者指定的操作。
2、图片/资源引用方式,攻击者将恶意请求嵌入到图片、脚本或其他资源引用中,并将其插入到受信任网站的页面。当用户访问页面时,浏览器会自动加载并发送恶意请求。
3、表单提交方式,攻击者创建一个包含恶意请求的表单,并将其隐藏在一个看似正常的页面中。当用户在该页面上执行某些操作(如点击按钮)时,浏览器会自动提交表单,从而执行攻击者指定的操作。
流程简述
Token是服务端生成的一串字符串,以作为客户端请求的一个令牌。
当第一次登录后,服务端会生成一个Token并返回给客户端,客户端后续访问时,只要携带这个Token就能完成认证。
应用场景
为了解决Session+Cookie机制暴露出的诸多问题,我们可使用Token的登录方式。
用户首次登录时:
用户访问a.com/login,输入账号密码,并点击登录。
服务端验证账号密码无误,建立Token。
服务端将Token返回给客户端,由客户端自由保存。
后续访问页面时:
用户访问a.com/page时,带上第一次登录时获取的Token。
服务端验证Token,有效则身份验证成功。
最常见的Token生成方式是使用JWT。
JWT(Json Web Token)作为一个开放的标准(RFC 7519),定义了一种简洁的,自包含的方法用于通信双方之间以Json对象的形式安全的传递信息。
因为数字签名的存在,这些信息是可信的,JWT可以使用HMAC算法或者是RSA的公私秘钥对进行签名。
JWT是经过多种算法拼接组合而成的字符串,下面分析一下其组成:
Open Authrization(开放授权), 它是一个开放标准(RFC 6749),允许用户让第三方应用访问该用户在某一网站上存储的私密资源,而无需将用户名和密码提供给第三方。比如,我们熟知的通过qq/微信/微博等登录第三方平台。
OAuth 1.0版本发布后有许多安全漏洞,所以在OAuth2.0里面完全废止了OAuth1.0,它关注客户端开发者的简易性,要么通过组织在资源拥有者和HTTP服务商之间的被批准的交互动作代表用户,要么允许第三方应用代表用户获得访问的权限。
授权访问令牌access token的方法(Grant Type)有下面四种,每一种都有适用的应用场景:
1、Authorization Code (授权码模式)。结合普通服务器端应用使用。
2、Implicit(简化模式)。结合移动应用或 Web App 使用。
3、Resource Owner Password Credentials。适用于受信任客户端应用,例如同个组织的内部或外部应用。
4、Client Credentials。适用于客户端调用主服务API型应用(比如百度API Store,不同项目之间的微服务互相调用)。
用户首次访问时,需要在认证中心登录:
认证中心完成登录后,继续访问a.com的其余页面,由于此时a.com已经存了Cookie信息,服务端直接认证成功。 如果要访问认证中心已存的b.com的页面,由于认证中心存在以前登录过的Cookie,也就不用再输入账号密码,直接返回第四步,下发ticket给b.com即可。
完成单点登录后,在同一套认证中心管理下,多个产品能够共享登录状态,但是还有一个问题:在一个产品中退出了登录状态,怎么让其余产品也退出登录?
原理并不难,回过头来看第5步,每个产品在向认证中心验证ticket时,能够顺带将本身的退出登录api发送到认证中心。当某个产品c.com退出登录时:
除了上述的认证方式,也可以引入第三方厂家提供的登录服务。如微博、微信、QQ等提供的登录认证接口,均能实现登录过程。
本文的引用仅限自我学习如有侵权,请联系作者删除。
参考知识
Web 认证机制相关概念解析
常见的登录验证方式