关于登录的实现

日常项目中用户的登录一般有两种方式,一种是使用 cookie 和 session ,一种是使用 token。前者一般用在前后端不分离的项目中,后者则相反。因为前后端分离的时候,如果想共享 cookie 要么再加一个前后端站点的上级站点,要么将后端服务器设置为前端服务器的上级,有点不伦不类。

使用 cookie 与 session 实现

单个站点

实现逻辑是用户登录成功后,将用户信息存入 session 并设置过期时间,前端之后每次访问带上用于区别用户的标识,后端会根据这个标识查找这个用户,如果用户没过期,允许访问并刷新过期时间,如果用户过期,则重新登录。

vote.test/index.php


// 这些 html 代码应该是用模板引擎的
$header = '<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body>';
echo $header;
$login = '<form action="/login.php" method="post">
   用户名:<input type="text" name="username"> <br>
   密码:<input type="text" name="password"> <br>
   <button>登录</button>
</form>';
echo $login;
$footer = '</body></html>';
echo $footer;

vote.test/login.php

<?php
session_start();

$username = $_POST['username'];
$password = $_POST['password'];
// 使用 $username 和 $password 查询数据库验证用户名密码是否相同

// 登录成功将用户名及登录过期时间存入 session
$expires = time() + 1800;
$_SESSION['username'] = [$username, $expires];
// 为前端页面设置 cookie ,也可以在前端用 js 设置,也可以不设置有效期,根据 session 的有效期
setcookie('username', $username, time() + 1800);

header("Location:/index.php");

多个站点单点登录

需要一个单点登录站点作为其它站点的上级站点,进行登录的校验。其它站点需要登录时,都会跳转到单点登录站点进行登录,在用户登录成功后,登录站点将用户信息存入 session 并设置过期时间,此时还需要设置一个子级站点可以共享的 cookie ,这样之后子级站点每次访问自己站点的功能,后端都需要先根据获取的 cookie 到单点登录站点获取用户信息,再处理下面的业务。单点登录站点的用户有效期刷新机制与单个站点相同。

vote.test/login.php

...
setcookie('username', $username, time() + 1800, 'http://.vote.test');
...

一个小点:session 的数据存储在服务器,与浏览器的通信是通过一个名为 SESSION_ID 的 cookie ,而一次会话的时间就是浏览器的打开和关闭的时间,浏览器关闭 SESSION_ID 删除,会话结束。

使用 token

实现逻辑是后端验证登录成功后,生成一个唯一 token 存储在服务器上(比如 redis 中),并返回给前端,前端每次访问后端的接口都把这个 token 作为请求头传递给后端,后端根据这个 token ,进行验证用户是否登录,刷新 token 有效期等操作。

单点登录的方式也很相似,把单点登录服务器登录的接口,其它站点每次访问各自站点的功能时,都先带上 token 请求一下单点登录服务器的验证接口,再进行接下来的操作。