账号密码登录
- 流程略过
手机验证码登录、邮箱登录
- 前端点击发送验证码,把手机号传给后端,后端生成随机数(或第三方平台生成),然后把号码和完整的短信内容(包括随机数)都发送给第三方短信平台
- 后端把收到的号码和随机数存到数据库里
- 用户收到短信后点登录,收集手机号和验证码传给后端进行对比,验证成功后登录成功
- 邮箱验证码和手机验证码逻辑基本都是一样的,用第三方邮箱平台,然后接收验证码的地方由手机号变为邮箱号
第三方账号快捷登录
扫码登录
扫码登录当中涉及到的三种角色:PC端、手机端、服务端
- PC端生成二维码:服务端必须给这个数据生成惟一的标识作为二维码ID,同时还应该设置过期的时间。PC端根据二维码ID等数据生成二维码。同时,服务端设置二维码的相应状态:未扫描、已成功、已失效
- 手机端登陆后,扫描二维码,带上手机端和设备绑定的token、二维码信息(二维码ID)请求服务端,进行认证
- 服务端根据手机端 token 和二维码 ID 生成 PC 端 token
- PC端生成二维码后,进行轮询、长轮询或 websocket 向服务端请求二维码状态,如果已成功,获取 PC token,登录成功。
微信扫码登陆
- 先在微信开放平台注册开发者帐号,并拥有一个已审核通过的网站应用,并获得相应的AppID和AppSecret,申请微信登录且通过审核后,可开始接入流程
- 页面中先引入微信登陆 js sdk 文件,传入 appid、redirect_uri等,拿到授权码 code 后走 OAuth2.0 授权流程
var obj = new WxLogin({
self_redirect:true,
id:"login_container", // 根据 id 选择器生成二维码
appid: "",
scope: "",
redirect_uri: "",
state: "",
style: "",
href: ""
});
指纹登录、刷脸登录
这个都是用于移动端也就是 iOS 和 Android,而且都需要 SDK
大致流程应该是需要一个用户确认开通这些功能的页面,或者授权获取信息弹窗等方式,让用户授权
本机号码免密一键登录
- 注:手机号掩码是指对手机号码进行部分隐藏,例如 137****1234
单点登录(SSO)
简单说就是在一个应用注册的账号可以同时在多个应用上登陆
比如淘宝+天猫+支付宝+阿里巴巴…,这几个随便登陆哪一个,再打开其他几个的网站就会自动进入登录状态
同域:
- 比如百度(baidu.com)、百度网盘(pan.baidu.com)、百度贴吧(tieba.baidu.com)、百度地图(map.baidu.com)…
- 首先需要把 Cookie 设置给顶级域,这样子他下面所有的子域都可以访问他的 Cookie
- 可以通过 domain 和 path 来控制哪些能不用登陆
不同域方式一:
- SSO 一般都需要一个独立的认证中心(CAS),子系统的登录均得通过passport,子系统本身将不参与登录操作
- 基本认证流程:用户统一在认证中心进行登录,登录成功后,认证中心记录用户的登录状态,并将 token 写入认证中心的 Cookie(全局会话),之后进入认证中心就会自动带上这个Cookie
- 子系统检查当前请求有没有用于验证身份的 Token,如果没有,说明用户在当前子系统中尚未登录,那么就将页面跳转至认证中心
- 如果认证中心带上自身Cookie的Token,发现用户尚未登录,则返回登录页面,等待用户登录
- 如果发现用户已经登录过了,就不会让用户再次登录了,而是会跳转回目标 URL,并在跳转前生成一个 Token,拼接在目标URL 的后面,回传给目标应用系统
- 子系统拿到 Token之后,还需要向认证中心确认下 Token 的合法性,防止用户伪造。确认无误后,子系统记录用户的登录状态,并将 Token 写入自身的Cookie(局部会话)
- 当用户再次访问当前子系统时,就会自动带上这个 Token,子系统验证 Token 发现用户已登录,于是就不会去认证中心
不同域方式二
- 嵌入了 iframe 场景
- 前端登陆后,将 Session ID (或 Token )保存到浏览器的 LocalStorage 中
- 然后通过 iframe + postMessage 将 token 可以通过跨域传输将它写入多个其他域下的 LocalStorage 中
// 应用1
const iframe = document.createElement('iframe')
iframe.src = 'http://www.app.com/static/bridge.html'
iframe.addEventListener('load', event => {
iframe.contentWindow.postMessage(token, 'http://www.app.com/static/bridge.html')
})
document.body.append(iframe)
// 其他应用
window.addEventListener('message', ({ data, origin, srouce }) => {
localStorage.setItem('AUTH-TOKEN', data)
})
// 获取 token
var token = result.data.token;
// 动态创建一个不可见的iframe,在iframe中加载一个跨域HTML
var iframe = document.createElement("iframe");
iframe.src = "http://app1.com/localstorage.html";
document.body.append(iframe);
// 使用postMessage()方法将token传递给iframe
setTimeout(function () {
iframe.contentWindow.postMessage(token, "http://app1.com");
}, 4000);
setTimeout(function () {
iframe.remove();
}, 6000);
// 在其他域中绑定一个事件监听器,当事件被触发时,把接收到的token数据写入localStorage
window.addEventListener('message', function (event) {
localStorage.setItem('token', event.data)
}, false);
单点登录的优缺点
优点
- 用户体验好,不需要记住多个账号和密码
- 提高开发效率
- 方便管理
缺点
- 不利于重构,因为涉及到的系统多,要重构的话需要兼容所有系统,就很麻烦
- 存在安全隐患,毕竟只需要登录一次,所有授权的应用都可以直接访问,就可能导致一些信息泄露