前后端分离常用的认证方式

原文参考:https://mp.weixin.qq.com/s/4ZgxcJn-kYCLjvA1foK_yQ

前后端分离常用的认证方式

前后端分离中前后端的交互是通过 API 进行的,那么其中的认证是少不了的。前后端分离中常用的认证方式有下面几种:

  • Session-Cookie
  • Token 验证
  • OAuth(开放授权)

Session-Cookie 方式

Session-Cookie 方式是我们开发 web 应用时最常用的认证方式。它的认证过程一般是这样的:

  • 1/ 用户浏览器向服务器发起认证请求,将用户名和密码发送给服务器。
  • 2/ 服务器认证用户名和密码,若通过则创建一个 session 对话,并将用户信息保存到 session 中。session 的信息可以是保存到服务器文件、共享外部存储、数据库等存储中,等下次请求时查询验证使用。
  • 3/ 服务器会将该 session 的唯一标识 ID,返回给用户浏览器,并保存在 cookie 中。
  • 4/ 用户请求其他页面时,浏览器会自动将用户的 cookie 携带上,并发起接口请求,服务端收到请求后,从 cookie 解析出 sessionID, 根据这个 sessionID 查询登录后并保存好的 session,若有则说明用户已登录,放行。

该方式是 MVC 架构中最常用的认证方案,在前后端分离中也是可以用的。几乎所有的 Web 框架都默认集成了 Session-Cookie 的认证方式,而且对 Session-Cookie 方式的安全性和稳定性方面都有很成熟的处理方案。

当前端代码使用后端 web 框架当做 web 容器驱动时,Session-Cookie 方案可作为首选的认证方案。

Token 方式

Token 方式是不同系统交互、前后端架构常用的认证方式。Token 方式的认证流程如下:

  • 1/ 用户使用用户名和密码登录,将用户名和密码发送给服务器。
  • 2/ 服务器验证用户名和密码,若正确,则签发 token,返回给用户。
  • 3/ 用户收到 token 后,将其存储起来,web 服务一般为 localStrage 或 cookie。
  • 4/ 用户请求其他资源页面时,会携带 token,一般放到 header 或参数中,发送给服务端。
  • 5/ 服务器收到后,验证 token,判断用户的正确性。

JWT(JSON Web Token)是最常用的一种 Token 认证方式,已成为 Token 认证的标准事实。JWT 方式将 Token 分段,使其可以保持少量数据,还增加了签名验证,确保了 token 的安全性。JWT 网上介绍的资料很多,这里不再赘述。不了解的,可参考下边这些资料:

  • JSON Web Token 入门教程[1]
  • JWT 官网[2]

OAuth 方式

OAuth(Open Authorization)是一个开放标准,允许用户授权第三方网站访问他们存储在服务端的用户信息。我们常见的的 QQ、微信等第三方登录便是 Auth 认证方式。OAuth 协议有 1.0 和 2.0 两个版本。相比较 1.0 版,2.0 版整个授权验证流程更简单更安全,也是目前最主要的用户身份验证和授权方式。

OAuth 更像是一种授权机制。数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据。系统从而产生一个短期的进入令牌(token),用来代替密码,供第三方应用使用。

在单纯的前后端分离系统中,OAuth 并不是常用的方式,它更多的应用在不同系统之间的授权交互。

对比思考

刨去不常用的 OAuth,这里对比两种前两种常用的认证方式 JWT Auth 和 Session-Cookie Auth ,到底谁才是前后端分离认证的最佳实践呢。从下面几个方向分析比对。

可扩展性

Session-Cookie 是有状态的服务,在服务端保存了 session 的信息。当服务端扩容的时候,需要考虑到 session 的共享问题,这个问题已有成熟的解决方案,可使用 session 复制、共享、持久化等方式解决,大多数的分布式 Web 框架已经集成了处理方案。JWT 验证方式是无状态的服务,服务端可随意扩缩容。

Session-Cookie 方式基于 Cookie,也就是必须是浏览器或支持 Cookie 的浏览器封装的框架,纯移动端无法使用。JWT 不同,不依赖 Cookie, 只要在本地可存储即可。

安全性

Web 开发中常见的两个安全问题 XSS(跨站点脚本攻击) 和 CRSF (跨站点请求伪造)。前者利用注入脚本到用户认证网站上,执行恶意脚本代码。后者则利用浏览器访问后端自动携带 cookie 的机制,来跨站伪造请求。XSS 只要我们对注入端,进行过滤、转义就能解决,CRSF 是我们重点关注的。

在 Session-Cookie 认证方式中,因为把 SessionID 保存在了 Cookie 中,很容易引起 CRSF 攻击。在大多数的 WEB 框架中有集成解决方案,如 Django 的 csrftoken 、Beego 的 xsrfToken 等。在使用 Session-Cookie 方案时建议开启 web 框架的 csrf 功能。

JWT 认证,可以把 Token 存放在 Cookie 或 localstorage。建议存在 localstorage,这样就彻底避免了 CRSF 攻击。

另外 JWT 有几个安全性的问题,需要注意:

  • 1/ JWT 是明文编码 JWT 的编码是明文 Base64 的一个编码,是可以反编译的。在使用 JWT 传输信息的时候,不要放置重要敏感信息,最好使用 https。
  • 2/ JWT 泄露问题 解决 JWT 的泄露问题是一个平衡的问题。有三种处理方式由轻到重,看你业务重要性酌情选择:
    • 将 JWT 的过期时间设置的很短,即使泄露也无关紧要。
    • 在服务端设计 JWT 的黑名单机制,将泄露的 Token 加黑名单即可。
    • 保存签发的 JWT,当 JWT 泄露时,直接设置失效。

性能

Session-Cookie 方案,因为后端服务存储了 Session 信息,在认证的时候需要查询,当有大量认证的时候是非常耗费资源的。JWT 可以把信息放到 token 中,只需要验证解码,使用签名验证 token 即可,相对来说效率会有提升。

从上面三个方面,我们分析了 Session-Cookie 和 JWT 方式各自的优缺点,和面对问题的一些应对方案。相信大家会有自己的心里选择。

抛开业务场景谈技术都是耍流氓。不同的业务场景,不同的架构设计,适用的认证方式也是不同的。这里按我自己的经验总结了下,什么情况下该使用那种认证方式,大家可参考。

适用 Session-Cookie 认证方案的情况:

  • 项目只有 web 端的情况;
  • 项目人员配置少,且前后端开发都会参与;
  • 项目前后端分离不彻底,前端使用后端 web 框架作为服务容器启动;

使用 JWT 认证方案的情况:

  • 项目人员配置充足,分工明确;
  • 项目除 web 端外还有移动端;
  • 临时的授权需求;
  • 纯后端系统之间的交互。

本文围绕前后端分离这个话题总结分享了前后端分离时的认证方案。这些仅仅是通用的一般方案,在具体的业务场景中,还有很多不典型的扩展的验证方案也是极好的,欢迎大家留言讨论自己心中的最佳认证方案。

参考及扩展阅读

  • 傻傻分不清之 Cookie、Session、Token、JWT[3]
  • 四种认证方式[4]
  • JWT 简介[5]
  • JWT 勿用[6]
  • (译)别再使用 JWT 作为 Session 系统!问题重重且很危险。[7]
  • OAuth 2.0 的一个简单解释[8]
  • OAuth 2.0 的四种方式[9]
原文地址:https://www.cnblogs.com/robinunix/p/13745116.html