跳至主要內容

网络

zfh大约 29 分钟约 8836 字

什么是同源策略

ajax请求时,浏览器要求当前网页和 server 必须同源(安全)

同源:协议、域名、端口,三者必须一致

手写一个简易的 ajax

function ajax(url, method = 'GET', data = null) {
  return new Promise(function (resolve, reject) {
    // 1
    const xhr = new XMLHttpRequest()
    xhr.responseType = 'json'
    // 2
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          resolve(xhr.response)
        } else if (xhr.status === 404) {
          reject(new Error('404 not Found'))
        }
      }
    }
    // 3
    xhr.open(method, url, true)
    // 4
    xhr.send(data)
  })
}
ajax('https://www.imooc.com/api/http/search/suggest?words=js').then((res) => {
  console.log(res)
})

跨域的常见实现方式

良苦用心啊!我把 7 大跨域解决方法原理画成 10 张图,做成图解!open in new window

编者按

各种 iframe 方式可传递数据,但组织和控制代码逻辑太复杂,鸡肋;

jsonp 前几年使用,现在浏览器兼容性高了,以及受限于仅 get 方式,逐步淘汰了;

nginx 反向代理是绕过去的方式,是从古至今通吃完美解决方案,缺点也许是服务器压力大一点,实际中那点压力根本不是大问题;同时反向代理更适合内部应用间访问和共享;

cors 才是真正的称得上跨域请求解决方案,因为请求存在跨域,结果是拿到了数据,也就是说服务器和浏览器之间进行了协商通信控制后,才得以允许或拒绝;

最后说明下,跨域请求产生时,请求是发出去了,也是有响应的,仅仅是浏览器同源策略,认为不安全,拦截了结果,不将数据传递我们使用罢了

目前公司普遍是前端本地使用 node 服务器代理,生产环境使用 nginx 做反向代理,转发到网关统一处理

CORS 跨域资源共享 纯服务端

跨域资源共享 CORS 详解open in new window

使用 CORS 跨域的过程

① 浏览器发送请求

② 后端在响应头中添加 Access-Control-Allow-Origin 头信息

③ 浏览器接收到响应

④ 如果是同域下的请求,浏览器不会额外做什么,这次前后端通信就圆满完成了

⑤ 如果是跨域请求,浏览器会从响应头中查找是否允许跨域访问

⑥ 如果允许跨域,通信圆满完成

⑦ 如果没找到或不包含想要跨域的域名,就丢弃响应结果

JSONP 过时

  1. 原理
    script 标签跨域不会被浏览器阻止
    JSONP主要就是利用script标签,加载跨域文件
  2. 使用JSONP 实现跨域
    服务器端准备好JSONP接口
    手动加载JSONP标签:
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>

  <body>
    <script type="text/javascript">
      const handleResponse = (data) => console.log(data)
    </script>
    <script src="https://www.imooc.com/api/http/jsonp?callback=handleResponse"></script>
  </body>
</html>

动态加载JSONP接口:

// 动态加载JSONP接口
const script = document.createElement('script')
script.src = 'https://www.imooc.com/api/http/jsonp?callback=handleResponse'
document.body.appendChild(script)
const handleResponse = (data) => {
  console.log(data)
}

HTTP 常见的状态码有哪些?

HTTP 状态码open in new window

分类:

  • 1XX:服务器收到请求

  • 2XX:请求成功,如 200

  • 3XX:重定向,如 302

  • 4XX:客户端错误,如 404

  • 5XX:服务端错误,如 500

常见状态码:

  • 200 成功
  • 301 永久重定向(配合location,浏览器自动处理)
  • 302 临时重定向 (配合location,浏览器自动处理)
  • 304 资源未被修改
  • 404 资源未找到
  • 403 没有权限
  • 500 服务器错误
  • 504 网关超时

http 哪些常见 header

request headers

  • Accept: 浏览器可接受的数据格式
  • Accept-Encoding:浏览器可接受的压缩算法,如 gzip
  • Accept-Languange: 浏览器可接受的语言,如 zh-CN
  • Connection: keep-alive 一次 TCP 连接重复使用
  • cookie
  • host
  • User-Agent:(简称 UA)浏览器信息
  • Content-type 发送数据的格式,如application/json

response headers

  • Content-type:返回数据的格式
  • Content-length:返回数据的大小,多少字节
  • Content-Encoding:返回数据的压缩算法
  • Set Cookie:用于设置客户端 cookie

缓存相关的 headers

  • Cache-Control response header
    • max-age 过期时间 单位:秒
    • no-cache:不用强制缓存,交给服务端处理(协商缓存)
    • no-store:不用强制缓存,也不让服务端处理,直接返回资源

两者共存,优先使用 Etag(Last-Modified 只能精确到秒级,如果资源被重复生成,而内容不变,Etag 更精确)

  • Last-Modifiedresponse header :资源的最后修改时间 If-Modified-Since request header
  • Etagresponse header :资源的唯一标识(字符串) If-None-Matchrequest header

讲一下 http 的缓存机制?

不同的刷新操作,对缓存的影响

正常操作(地址栏输入 url,跳转链接,前进后退),强制缓存有效,协商缓存有效

手动刷新(cmd+r|F5),强制缓存失效,协商缓存有效

强制刷新(shift+cmd+r|ctrl+F5),强制缓存失效,协商缓存失效

http缓存流程图
http缓存流程图

讲一下 https 的过程?

https过程
https过程

什么是 xss 攻击 如何预防 xss 攻击

XSS攻击指的是跨站脚本攻击,是一种代码注入攻击。攻击者通过在网站注入恶意脚本,使之在用户的浏览器上运行,从而盗取用户的信息如cookie

攻击者可以通过这种攻击方式可以进行以下操作:

  1. 获取页面的数据,如 DOM、cookie、localStorage
  2. DOS 攻击,发生合理请求,占用服务器资源,从而使用户无法访问服务器
  3. 破坏页面结构
  4. 流量劫持,将链接指向某网站

根据攻击的来源,XSS 攻击可分为存储型、反射型和 DOM 型三种。

存储型 XSS

存储型 XSS 的攻击步骤:

  1. 攻击者将恶意代码提交到目标网站的数据库中。
  2. 用户打开目标网站时,网站服务端将恶意代码从数据库取出,拼接在 HTML 中返回给浏览器。
  3. 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
  4. 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

这种攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。

反射型 XSS

反射型 XSS 的攻击步骤:

  1. 攻击者构造出特殊的 URL,其中包含恶意代码。
  2. 用户打开带有恶意代码的 URL 时,网站服务端将恶意代码从 URL 中取出,拼接在 HTML 中返回给浏览器。
  3. 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
  4. 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

反射型 XSS 跟存储型 XSS 的区别是:存储型 XSS 的恶意代码存在数据库里,反射型 XSS 的恶意代码存在 URL 里。

反射型 XSS 漏洞常见于通过 URL 传递参数的功能,如网站搜索、跳转等。

由于需要用户主动打开恶意的 URL 才能生效,攻击者往往会结合多种手段诱导用户点击。

POST 的内容也可以触发反射型 XSS,只不过其触发条件比较苛刻(需要构造表单提交页面,并引导用户点击),所以非常少见。

DOM 型 XSS

DOM 型 XSS 的攻击步骤:

  1. 攻击者构造出特殊的 URL,其中包含恶意代码。
  2. 用户打开带有恶意代码的 URL。
  3. 用户浏览器接收到响应后解析执行,前端 JavaScript 取出 URL 中的恶意代码并执行。
  4. 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

DOM 型 XSS 跟前两种 XSS 的区别:DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞,而其他两种 XSS 都属于服务端的安全漏洞

预防措施

预防存储型和反射型 XSS 攻击 后端

  1. 不使用服务端渲染,纯前端渲染(在很多内部、管理系统中,采用纯前端渲染是非常合适的。但对于性能要求高,或有 SEO 需求的页面,我们仍然要面对拼接 HTML 的问题)

  2. 转义 html

预防 DOM 型 XSS 前端

  1. 在使用 .innerHTML、.outerHTML、document.write() 时要特别小心,不要把不可信的数据作为 HTML 插到页面上,而应尽量使用 .textContent、.setAttribute() 等

  2. 如果用 Vue/React 技术栈,并且不使用 v-html/dangerouslySetInnerHTML 功能,就在前端 render 阶段避免 innerHTML、outerHTML 的 XSS 隐患。

3 . DOM 中的内联事件监听器,如 location、onclick、onerror、onload、onmouseover 等,a 标签的 href 属性,JavaScript 的 eval()、setTimeout()、setInterval() 等,都能把字符串作为代码运行。如果不可信的数据拼接到字符串中传递给这些 API,很容易产生安全隐患,请务必避免。

其他 XSS 防范措施

  1. CSP Content Security Policy

通常有两种方式来开启 CSP,一种是设置 HTTP 首部中的 Content-Security-Policy,一种是 设置 meta 标签的方式

  • 禁止加载外域代码,防止复杂的攻击逻辑。
  • 禁止外域提交,网站被攻击后,用户的数据不会泄露到外域。
  • 禁止内联脚本执行(规则较严格,目前发现 GitHub 使用)。
  • 禁止未授权的脚本执行(新特性,Google Map 移动版在使用)。
  • 合理使用上报可以及时发现 XSS,利于尽快修复问题。
  1. cookie 设置 http-only,使得脚本无法获取

  2. 使用验证码,避免脚本伪装成用户执行操作

  3. 输入内容长度控制虽然无法完全防止 XSS 发生,但可以增加 XSS 攻击的难度

什么是 CSRF 攻击 如何预防 CSRF 攻击

CSRF 攻击指的是跨站请求伪造攻击,攻击者诱导用户进入一个第三方网站,然后该网站向被攻击网站发送跨站请求。如果用户在被攻击网站中保存了登录状态,那么攻击者就可以利用这个登录状态,绕过后台的用户验证,冒充用户向服务器执行一些操作

一个典型的 CSRF 攻击有着如下的流程:

  • 受害者登录 a.com,并保留了登录凭证(Cookie)。
  • 攻击者引诱受害者访问了 b.com。
  • b.com 向 a.com 发送了一个请求:a.com/act=xx。浏览器会默认携带 a.com 的 Cookie。
  • a.com 接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求。
  • a.com 以受害者的名义执行了 act=xx。
  • 攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让 a.com 执行了自己定义的操作。

CSRF 攻击的本质是利用 cookie 会在同源请求中携带发送给服务器的特点,以此来实现用户的冒充

三种常见类型的攻击类型

GET 类型的 CSRF

GET 类型的 CSRF 利用非常简单,只需要一个 HTTP 请求,一般会这样利用:

![](https://awps-assets.meituan.net/mit-x/blog-images-bundle-2018b/ff0cdbee.example/withdraw?amount=10000&for=hacker)

在受害者访问含有这个 img 的页面后,浏览器会自动向http://bank.example/withdraw?account=xiaoming&amount=10000&for=hacker发出一次 HTTP 请求。bank.example 就会收到包含受害者登录信息的一次跨域请求。

POST 类型的 CSRF

这种类型的 CSRF 利用起来通常使用的是一个自动提交的表单,如:

<form action="http://bank.example/withdraw" method="POST">
  <input type="hidden" name="account" value="xiaoming" />
  <input type="hidden" name="amount" value="10000" />
  <input type="hidden" name="for" value="hacker" />
</form>
<script>
  document.forms[0].submit()
</script>

访问该页面后,表单会自动提交,相当于模拟用户完成了一次 POST 操作。

POST 类型的攻击通常比 GET 要求更加严格一点,但仍并不复杂。任何个人网站、博客,被黑客上传页面的网站都有可能是发起攻击的来源,后端接口不能将安全寄托在仅允许 POST 上面。

链接类型的 CSRF

链接类型的 CSRF 并不常见,比起其他两种用户打开页面就中招的情况,这种需要用户点击链接才会触发。这种类型通常是在论坛中发布的图片中嵌入恶意链接,或者以广告的形式诱导用户中招,攻击者通常会以比较夸张的词语诱骗用户点击,例如:

<a
  href="http://test.com/csrf/withdraw.php?amount=1000&for=hacker"
  taget="_blank"
>
  重磅消息!!
  <a
/></a>

由于之前用户登录了信任的网站 A,并且保存登录状态,只要用户主动访问上面的这个 PHP 页面,则表示攻击成功。

防范措施

  1. 同源检测:服务器根据 http 请求头中 origin 或者 referer 信息来判断请求是否为允许访问的站点,从而对请求进行过滤。当 origin 或者 referer 信息都不存在,直接阻止请求。这种方式的缺点是有些情况下 referer 可以被伪造,同时还会把搜索引擎的链接给屏蔽了。所以一般网站会允许搜索引擎的页面请求,但是相应的这种请求方式也可能被攻击者利用。
  2. 使用 CSRF Token 进行验证,服务器向用户返回一个随机数 Token,当网站再次发起请求时,在请求参数中加入服务端返回的 token,然后服务器对这个 token 进行验证。这种方法解决了使用 cookie 单一验证方式时,可能会被冒用的问题,但是这种方法存在一个缺点就是,我们需要给网站中的所有请求都添加上这个 token,操作比较繁琐。还有一个问题是一般不会只有一台网站服务器,如果请求经过负载平衡转移到了其他的服务器,但是这个服务器的 session 中没有保留这个 token 的话,就没有办法验证了。这种情况可以通过改变 token 的构建方式来解决。

扩展

可以将 token 的构建方式改为无状态(stateless)的方式,不再依赖服务器端的 session。以下是一些改变 token 结构的方式:

  1. 使用 JWT:JWT(JSON Web Token)是一种开放标准,可以将用户的身份信息以 JSON 格式进行编码,并使用签名保证数据的完整性和安全性。JWT 可以在客户端生成,不需要在服务器端进行存储,因此可以避免 session 不一致的问题。
  2. 使用时间戳和随机数:可以将 token 的值设置为由时间戳和随机数拼接而成的字符串,例如"timestamp-random",其中时间戳和随机数可以使用当前的 UTC 时间和随机生成的字符串。客户端在发送请求时将这个 token 作为请求参数或请求头中的值传递给服务器端,服务器端对这个 token 进行验证即可。
  3. 使用加密算法:可以将 token 的值使用对称或非对称加密算法进行加密,例如 AES、RSA 等。客户端在发送请求时将加密后的 token 作为请求参数或请求头中的值传递给服务器端,服务器端使用相应的密钥对 token 进行解密并验证其合法性。
  1. 对 cookie 进行双重验证,服务器在用户访问网站页面时,向请求域名注入一个 cookie,内容为随机字符串,然后当用户再次向服务器发送请求的时候,从 cookie 中取出这个字符串,添加到 URL 参数中,然后服务器通过对 cookie 中的数据和参数中的数据进行比较,来进行验证。使用这种方式是利用了攻击者只能只能利用 cookie,但是不能访问获取 cookie 的特点。并且这种方法比 CSRF Token 的方 法更加方便,并且不涉及到分布式访问的问题。这种方法的缺点是如果网站存在 XSS 漏洞的,那么这种方式会失效(攻击者可以拿到 cookie)。同时这种方式不能做到子域名的隔离。
  2. 在设置 cookie 属性的时候设置Samesite,限制 cookie 不能被第三方使用,从而避免被攻击者利用。两个模式:严格模式,任何情况下的 cookie 都不能被第三方使用,宽松模式:cookie 可以被 GET 请求,且会发生页面跳转的请求所利用

什么是中间人攻击 如何防范中间人攻击

中间人是指攻击者与通讯的两端分别创建独立的联系,并交换其所收到的数据,使通讯的两端认为他们正在通过一个私密两届与对方直接对话,但事实上整个会话都被攻击者完全控制。 在中间人攻击中,攻击者可以拦截通讯双方的通话并插入新的内容。

攻击过程如下:

  • 客户端发送请求到服务端,请求被中间人截获
  • 服务器向客户端发送公钥
  • 中间人截获公钥,保留在自己手上。然后自己生成一个伪造的公钥,发给客户端
  • 客户端收到伪造的公钥后,生成加密 hash 值发给服务器
  • 中间人获得加密 hash 值,用自己的私钥解密获得真秘钥,同时生成假的加密 hash 值,发给服务器
  • 服务器用私钥解密获得假密钥,然后加密数据传输给客户端

网站劫持有哪几种 如何防范

DNS 劫持

输入京东被强制跳转到淘宝

  • DNS 强制解析:通过修改运营商的本地 DNS 记录,来引导用户流量到缓存服务器
  • 302 跳转的方式:通过监控网络出口的流量,分析判断哪些内容是可以进行劫持处理的,再对劫持的内存发起 302 跳转的回复,引导用户获取内容

HTTP 劫持

访问谷歌但是一直有贪玩蓝月的广告

由于 http 明文传输,运营商会修改你的响应内容(加广告)

DNS 劫持由于涉嫌违法,已经被监管起来,现在很少会有 DNS 劫持,而 http 劫持依然非常盛行,最有效的办法就是全站 HTTPS,将 HTTP 加密,这使得运营商无法获取明文,就无法劫持你的响应内容。

登录的实现方案有哪些

HTTP 是一种无状态的协议。无状态是指协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。即我们给服务器发送 HTTP 请求之后,服务器根据请求返回数据,但不会记录任何信息。

为了解决 HTTP 无状态的问题,出现了 Cookie。

Cookie 是服务器端发送给客户端的一段特殊信息,这些信息以文本的方式存放在客户端,客户端每次向服务器端发送请求时都会带上这些特殊信息。

在 B/S 系统中,登录功能通常都是基于 Cookie 来实现的。当用户登录成功后,服务端会将登录状态记录到 Session 中,同时需要在客户端保存一些信息(SessionId),并要求客户端在之后的每次请求中携带它们。

在这样的场景下,使用 Cookie 无疑是最方便的,因此我们一般都会将 SessionId 保存到 Cookie 中,当服务端收到请求后,通过验证 Cookie 中的 SessionId 来判断用户的登录信息。

实现流程:

  • 用户输入用户名和密码,前端将用户提交的用户名和密码发送到后端进行验证。
  • 后端验证用户信息是否正确,并创建一个SessionSession是一种服务器端保存用户会话信息的机制,用于识别多次请求之间的逻辑关系。
  • 后端将Session ID(通常是一个随机的字符串)返回给前端,并通过 Cookie 的方式将Session ID保存在浏览器中。这样就可以保证当用户再次发送请求时,后端可以通过该 Session ID 来识别用户身份,并完成相关的操作。
  • 在后续的请求中,浏览器会自动将保存的 Cookie 信息发送到后端进行验证,如果 Session ID有效,则返回相应的数据。如果 Session ID 失效或者不存在,则需要重新登录获取新的 Session ID
  • 在用户退出时,后端需要删除对应的 Session 信息,以保证安全性。

需要注意的是,CookieSession 方案也存在一些安全问题。例如,如果攻击者可以获取到 Cookie 信息,则可以模拟用户身份进行恶意操作。因此,在实现时需要考虑添加一些安全措施,如:

  • 使用 HTTPS 协议来加密通信内容,防止中间人攻击。
  • 设置 Cookie 的 HttpOnly 属性为 true,以防止脚本获取到 Cookie 信息。
  • 尽量减少 Session 的有效期,以避免 Session 被盗用的风险。
  • 在前端和后端均验证用户身份,防止伪造登录请求。

缺点:

  • 安全性问题:由于 Session ID 存储在 Cookie 中,如果攻击者获取到该 Cookie 信息,则可以模拟用户身份进行恶意操作。为了解决这个问题,需要采取一些安全措施,如使用 HTTPS 协议加密通信内容、设置 CookieHttpOnly 属性为 true 等。
  • 跨域问题:由于 Cookie 只能在同域名下共享,因此跨域访问时无法访问到对应的 Cookie 信息。这时,可能需要采用一些其他的跨域解决方案,如 JSONP、CORS 等。
  • 扩展性问题:由于 Session 信息存储在服务器端,当系统扩展到多台服务器时,需要采用一些集中式的 Session 管理方案,否则会出现 Session 不一致或者丢失等问题。
  • 性能问题:由于 Session 信息存储在服务器端,因此每次请求都需要从服务器读取 Session 信息,这可能会导致性能问题。为了解决这个问题,可以采用一些缓存方案来提高访问速度。
  • 一些移动设备和浏览器可能会禁用 CookieSession 机制,这会导致无法正常登录。

Token 登录

Token 是通过服务端生成的一串字符串,以作为客户端请求的一个令牌。当第一次登录后,服务器会生成一个 Token 并返回给客户端,客户端后续访问时,只需带上这个 Token 即可完成身份认证。

实现流程:

  • 用户输入用户名和密码,前端将用户提交的用户名和密码发送到后端进行验证。
  • 后端验证用户信息是否正确,并生成一个 Token。Token 是一串加密的字符串,包含了用户的身份信息和权限等相关信息。
  • 后端将 Token 返回给前端,并保存在客户端的 LocalStorage 或者 SessionStorage 中。
  • 每次向后端发送请求时,前端都需要在请求头部携带 Token 信息。
  • 后端接收到请求后会从 Token 中解析出用户身份信息,并通过权限校验等操作来判断请求是否合法。
  • 如果校验通过,则返回相应的数据,否则返回错误信息。
  • 在用户退出时,前端需要删除保存的 Token 信息。

需要注意的是,由于 Token 信息存储在客户端,因此不同于 Session 机制,它可以轻松地跨域使用,而且不需要考虑 Session 共享、分布式管理等问题。同时,由于 Token 机制不依赖服务器端的资源,因此在大规模高并发访问时,它具有更好的性能表现。

然而,由于 Token 信息存储在客户端,因此存在一定的安全风险,例如 Token 被盗用、被篡改等问题。为了保证安全性,需要采取一些安全措施,如:

  • 使用 HTTPS 协议来加密通信内容,防止中间人攻击。
  • 设置 Token 的过期时间,以避免 Token 长时间存储在客户端而被恶意利用。
  • 在前端和后端均验证 Token 信息,防止伪造登录请求。
  • 根据实际需求对 Token 进行加密处理,以增加破解难度。

Token 的生成方式通常有以下几种:

  • 随机字符串:可以使用一些随机数生成算法,如 UUID、Snowflake 等来生成一个随机的字符串作为 Token。由于随机字符串本身就是随机分布的,因此具有很高的安全性。

  • JWT(JSON Web Token):JWT 是一种基于 JSON 格式的开放标准(RFC 7519),用于在多方之间安全地传输信息。它将用户身份信息和权限等相关信息编码成一个 JSON 对象,并通过数字签名或者加密等方式进行验证和保护。JWT 除了可以用于 Token 登录外,还可以用于 API 认证、单点登录等场景。

  • Hash 值:可以将用户身份信息和时间戳等参数通过某种散列函数计算出一个 Hash 值,并将该 Hash 值作为 Token 返回给客户端。由于 Hash 值具有不可逆性和唯一性,因此也具有较高的安全性。

无论采用哪种方式生成 Token,都需要结合实际业务场景和安全需求来选择,并且需要对 Token 进行加密或者数字签名等操作来保障其安全性。同时,在 Token 的过期时间、密钥管理、Token 注销等方面都需要考虑相应的安全措施。

Token 登录的缺点:

  • 安全性问题:由于 Token 存储在客户端,因此存在被盗用、伪造、篡改等风险。为了解决这个问题,需要采取一些安全措施,如使用 HTTPS 协议加密通信、设置 Token 的过期时间和加密、数字签名等操作。 线程安全问题:由于 Token 无状态,因此不支持同步机制,可能存在线程安全问题。例如,当同时有多个请求同时使用相同的 Token 时,可能会导致重复登录等问题。
  • 扩展性问题:由于 Token 信息存储在客户端,因此对于大规模分布式系统而言,如果需要多台服务器之间共享 Token,则需要采用一些集中式的 Token 管理方案。 依赖前端处理:由于 Token 存储在客户端,因此需要前端代码来处理 Token 信息的存储和发送,这增加了前端代码的复杂度和维护成本。
  • Token 泄露问题:由于 Token 是长期有效的,一旦被泄露,则会存在更长时间的安全风险。为了避免这个问题,需要对 Token 进行定期更新或者注销等操作。

SSO 单点登录

SSO(Single Sign-On,单点登录)是一种在多个应用程序(比如 Web 服务)中实现认证和授权的方法。它允许用户只需登录一次,就可以访问多个应用程序,大大提高了用户体验和工作效率。

基本流程:

  • 用户通过浏览器访问第一个应用程序,并输入用户名和密码进行登录。
  • 第一个应用程序验证用户信息后,生成一个 Token 并将该 Token 返回给浏览器端。同时,它会将 Token 与该用户的身份信息绑定并存储在一个共享的认证数据源中,如 LDAP、数据库等。
  • 用户再次访问另一个应用程序时,该应用程序检查用户是否已经登录过。如果用户未登录,则引导用户到第一个应用程序进行登录;如果用户已经登录,则从共享的认证数据源中获取用户的身份信息,并生成一个新的 Token 返回给浏览器端。
  • 浏览器将 Token 发送给第二个应用程序,第二个应用程序使用相同的认证数据源来验证 Token,以确认该用户是否有权限访问该应用程序。
  • 如果 Token 有效,则第二个应用程序返回相应的数据;否则,它要求用户重新进行登录或者提示用户无权访问。
  • 用户访问其他应用程序时,重复上述过程。

实现方式:

  • 基于 Cookie 实现

该实现方式将 Token 存储在 Cookie 中,并通过浏览器的同源策略来共享 Token 信息。由于 Cookie 只能在同域名下共享,因此该方式仅适用于同域名下的应用程序。

  • 基于 Session 实现

该实现方式将 Token 信息存储在服务器端的 Session 中,并通过 Session ID 来共享 Token 信息。由于 Session 机制通常需要依赖某种中心化的 Session 管理系统,因此实现较为复杂。

  • 认证中心

认证中心就是一个专门负责处理登录请求的独立的 Web 服务。用户统一在认证中心进行登录,登录成功后,认证中心记录用户的登录状态,并将 Token 写入 Cookie。(注意这个 Cookie 是认证中心的,应用系统是访问不到的)。

应用系统检查当前请求有没有 Token,如果没有,说明用户在当前系统中尚未登录,那么就将页面跳转至认证中心进行登录。由于这个操作会将认证中心的 Cookie 自动带过去,因此,认证中心能够根据 Cookie 知道用户是否已经登录过了。如果认证中心发现用户尚未登录,则返回登录页面,等待用户登录,如果发现用户已经登录过了,就不会让用户再次登录了,而是会跳转回目标 URL ,并在跳转前生成一个 Token,拼接在目标 URL 的后面,回传给目标应用系统。

应用系统拿到 Token 之后,还需要向认证中心确认下 Token 的合法性,防止用户伪造。确认无误后,应用系统记录用户的登录状态,并将 Token 写入 Cookie,然后给本次访问放行。(这个 Cookie 是当前应用系统的,其他应用系统是访问不到的)当用户再次访问当前应用系统时,就会自动带上这个 Token,应用系统验证 Token 发现用户已登录,于是就不会有认证中心什么事了。

此种实现方式相对复杂,支持跨域,扩展性好,是单点登录的标准做法。

  • 基于 OAuth 实现

该实现方式采用 OAuth 协议来实现用户身份验证和授权。OAuth 是一个开放标准,用于在不同域名下的应用程序之间安全地共享资源和授权访问。该实现方式具有良好的兼容性和可扩展性,但需要额外的授权服务器和令牌管理机制。

  • 基于 OpenID Connect 实现

该实现方式是在 OAuth2.0 协议上构建的一个开放标准,用于实现用户身份验证和授权。它继承了 OAuth 的优点,并提供了更丰富的身份认证和授权机制。该实现方式具有较高的兼容性和安全性,但需要额外的授权服务器和令牌管理机制。

SSO 单点登录退出:

  • 单点注销:该方式是指用户在任一应用程序中进行注销操作时,可以自动将其他应用程序中的会话和相关信息一并清除。这通常需要使用回调 URL 和 Token 等机制来实现。
  • 局部注销:该方式是指用户只在当前应用程序中进行注销操作,并不会影响其他应用程序。在局部注销后,用户需要重新输入用户名和密码才能再次访问该应用程序。
  • 全局注销:该方式是指用户在某个应用程序中进行注销操作,可以清除所有应用程序中的会话和相关信息。这通常需要采用集中式的 Token 管理机制,并需要对 Token 进行撤销或者更新等操作。

SSO 单点登录的缺点:

  • 单点故障:由于单点登录系统需要负责所有应用程序的身份认证和授权,一旦发生故障或被攻击,则会影响所有应用程序的正常运行。
  • 安全问题:由于单点登录系统涉及到多个应用程序的身份认证和授权,因此安全性问题尤为重要。如果认证系统遭受攻击,则可能导致多个应用程序的信息泄露或数据损坏。
  • 中心化依赖:由于单点登录系统是集中式的,因此对于大规模分布式系统而言,如果需要多台服务器之间共享认证信息,则需要采用一些集中式的认证管理方案。
  • 可扩展性问题:由于单点登录系统需要处理多个应用程序之间的身份认证和授权,因此在实现时需要考虑其可扩展性问题。例如,在增加新的应用程序时,单点登录系统需要进行相关配置和调整,以保证其正常运行。
  • 维护成本:由于单点登录系统需要负责多个应用程序的身份认证和授权,因此其维护和管理成本相对较高。例如,在增加新的应用程序或更改现有应用程序时,需要对单点登录系统进行相应的调整和测试,以确保其正常运行。
上次编辑于:
本站勉强运行 小时