Vue 实现前后端分离站点登录态处理

最近在学习 Vue 开发,实现一个动态站点,很重要的一个功能就是实现用户的登录。在我以前熟知的前后端混合的项目中,实现用户登录是一个很平凡的事情,以至于我甚至一下子都想不起来它实现的方法和原理。

在前后端分离的网站里,到底怎么去实现用户的登录,验证等等功能呢?

前后端混合开发下的登录和验证

首先来回顾一下,在前后端混合开发模式下,我们是如何实现这个功能的。

登录

用户访问一个网站,服务器检查到当前用户没有登录态,则会跳转到登录页面。登录页面(login)自身不需要检查登录态,是任何人都可以访问的,一般就是一个表单,请用户输入用户名和密码,可能也提供用户名密码验证以外的其他登录方式,比如扫码,比如三方登录,比如短信验证等等,后面会提到。

登录表单被提交后,后台服务器会检验用户名密码是否正确,然后跳转到用户原本想访问的目标页面去。后台服务器会提供一个类似 identity 或者叫 user 的组件,调用其 login 方法,即实现了用户的登录。

那么 login 方法做了哪些事情呢?一般会在后台服务器创建一个会话 Session,然后将当前登录用户的信息,保存在 Session 中,然后在 Cookie 里发送一个 session_id,以确保每次用户登录的时候,服务器都可以通过 session_id 来恢复用户和服务器的会话。

验证

检验一个用户当前的请求是否处于登录状态,也即登录态验证,就比较明确了。就是从 Cookie 中读取用户的 session_id,进行安全验证后,通过此 id 在服务器查询对应的 Session,然后恢复了用户访问的上下文信息。

以上就是一个典型的前后端混合开发模式下的网站,登录和验证的方法和过程。

前后端分离开发下的登录和验证

那么在前后端分离后,登录和验证的方法又是什么样子呢?我想,从本质上,不应该有什么不同。只要它是一个 Web 站点,通过 HTTP 协议访问,那么仍然是无状态的,也即,还是要在应用中设置某种机制来实现登录态的保持。

如果,我们仍然把它当做一个网站来看,那么每次对服务器的请求,仍然是会带有 Cookie,所以,还可以使用 session_id 在服务器恢复用户的上下文信息。而 Cookie 管理是浏览器约定好的。只要对服务器发起请求,就会自动带有 Cookie。

所以,服务器验证客户端请求的登录态是跟从前一样的。区别在于,前台站点是一个纯前端的站点,那么整个应用如何知道自己当前处于登录状态呢?在登录成功后,根据登录 login API 的返回值,前台要管理好登录的状态。

如果,用户从一个特定网址,直接访问前台站点,那么,前台代码需要读取 Cookie 来确定自己当前是否已经处于登录状态,这是一种方法。还有一种方法是,前台直接调用一个后台 API,看看后台是否会报 403 错误,如果报错,说明当前浏览器上没有有效的 Cookie,如果没有报错,正确返回了值,则说明当前用户的登录态有效。这个 API,一般可以选择一个拉取当前登录用户 Profile 的 API。如果调用成功,正好将用户的登录态在前台恢复过来。

前台还有另外一种形态,就是 SPA,也就是所谓的单页应用,这种应用本质上并没有什么不同,只是,有时候,会装入到不同的容器里,未必是浏览器。比如用 Electron 之类的方案,变成客户端 App 来使用。我不是很了解此类应用,是否还会像浏览器这样去管理 Cookie,如果不是的话,可以完全像客户的那样,使用 JWT 一类的 token 来进行登录态的管理。

这就需要服务器端的配合,返回构造的 JWT,然后前台维护好 JWT,就可以在每次请求都带上,实现登录态的验证和会话的恢复。

三方登录

三方登录,其实是借助第三方平台的账号体系(IdP),实现登录验证的方法。在 Web 开发领域,我们应用最广的就是 OAuth2,其实还有其他的,比如 SAML,CAS 等等。我不熟悉,就不展开了。

使用 OAuth2 进行登录的时候,首先会跳转到第三方网站的登录页面,完成身份验证后,会跳转到之前制定的 callback 地址去,在前后台混合的网站里,这个 callback 会将请求参数中携带的 authorization_code 通过后台 server-to-server 调用 API,置换成 access_token,然后给前台发送包含 session_id 的 Cookie。

那么在前后端分离的网站里,这个步骤仍然不可以缺少。只是在发送这个 Cookie 的同时,给浏览器发送信号,要求前台跳转到用户的目标画面上。值得注意的是,在三方登录的流程中,前台的逻辑,并没有调用到 login 这个 API,所以并不知道用户已经登录成功的消息,而是在 Cookie 准备完毕后,直接跳入了目标页面。

这个时候,就必须用到上文提及的,通过主动访问 Cookie 或者通过试探性调用 Profile API 这样的动作来探知当前用户的登录态,以实现登录验证。

总结

以上,就是我关于在 Vue 实现前后端分离站点时,登录和验证处理方法的一些总结和思考。总体来说,还是很简单的,就是抓住问题的本质,这仍然是在 HTTP 协议下网站登录的相关处理。把握住这个实质就不难想通剩下所有的问题。只是,有时候,难免糊涂,自己把自己绕进去了,引以为戒。