前端轻松拿捏!最简全栈登录认证和权限设计!

本项目代码已开源,具体见:

前端工程:vue3-ts-blog-frontend

后端工程:express-blog-backend

数据库初始化脚本:关注公众号程序员白彬,回复关键字“博客数据库脚本”,即可获取。

前端走向全栈,从这个项目开始准没错!

前言

你或许作为前端的课代表,开发了很多高级的登录功能,比如扫码登录、手机号一键登录、第三方授权登录、生物认证登录等,对 OAuth、JWT、双 Token 等关键词也能脱口而出,但是你可能还从未以一个全栈的身份完整地开发过一个登录功能。没关系,本文的目的就是解决你的这份忧虑,从一个极简的全栈登录认证功能入手,打破这个枷锁!

前几篇文章提到过,在博客系统中,我们需要后台管理功能去维护我们的文章、留言评论等内容。既然是这样,后台管理的安全问题也得考虑,登录和权限设计是非常有必要的。

登录认证

常规的认证方式就是基于 Session 会话的认证,用户的身份信息是与 Web Session 绑定在一起的,这是至今依然流行的认证方案,经得起时间的考验!我们来梳理一下。

首先,HTTP 是无状态的,HTTP 协议本身并不保存客户端与服务器之间交互的状态信息。每当客户端向服务器发出请求时,服务器都会独立处理这个请求,不会考虑上下文关系。

而基于 HTTP 的 Web 应用,通常有着身份认证类需求,通过身份信息去识别用户,这其实是有状态的。

Cookie 的设计就是为了解决 HTTP 无状态的问题,通过头部字段 Cookie 和 Set-Cookie 来携带一些状态信息,这些状态信息与服务端的 Session 结合在一起,就可以让 HTTP 请求变成有状态的请求。

基于此,我们可以完成登录认证等功能。

以本项目为例,使用的数据库是 MySQL,user 表中设计了 token 这个字段用于用户会话身份的识别。

image.png

由于 Session 有唯一性,可以唯一标识一个客户端会话,Session 中有唯一的 Session ID,这个 Session ID 可以与数据库 user 表的 token 字段结合起来使用,如果二者是匹配的,就找到了对应的用户。

因此,我们只要在用户登录认证的时候,把这个 Session ID 写入到 token 字段中,后续鉴权时就可以依据 Session ID 查询用户表。

当然也不一定非得将 Session ID 作为 token,只要是能和 Session 联系起来的唯一值,理论上都可以作为 token。

权限

再来说权限,我们知道,为了实现一个产品功能,背后可能会设计很多个后端接口,前端会调用这些接口,进行逻辑和数据处理,最终呈现出产品界面效果。

但是,有的功能并不希望开放给普通用户使用,比如发布文章、审核评论等,这应该是博主才能使用的功能。

这就需要权限的控制,权限的控制会涉及到前端和后端

比如发布文章这个功能,如果你仅仅是在前端拦截了用户进入发布文章界面,也并非是安全的,因为有意要攻击系统的人会尝试直接调接口攻击后端,甚至是入侵数据库。

既然可以直接攻击后端和数据库,那么前端的防护还有意义吗?有的,防不了小人,先防君子。除此之外,逻辑上理应如此,该拦截的还是得拦截,用户体验也会好一点。

举个例子,假设一个普通用户通过一个链接就进入了你的后台管理系统,虽然接口没调成功,但是是不是也很尬?用户会觉得你的前端开发很水。

具体怎么做呢?我们来看具体实现。

登录的实现

先看登录是如何实现的。由于博客系统暂时不对外开放注册,只需要一个管理员账号即可,直接插入到用户表中即可,不需要增加业务控制器来维护。

image.png

我们使用传统的账号密码登录方式,用户名对应 user 表中的 user_name 字段,密码对应 password 字段,是经过了 SHA256 HASH 得到,保证密码不容易被逆运算破解。

为了提高安全性,我们还需要引入一个图片验证码的功能。

image.png

图片验证码的基本原理是:

  1. 当用户请求验证码时,后端在指定的字符序列中生成一串随机字符,并依据其内容生成一张验证码图片,图片中包含生成的随机字符。
  2. 将随机字符串保存在 Session 中,并把验证码图片返回给前端展示。
  3. 前端只能拿到验证码图片,并不知道验证码的值,需要通过输入去校验,所以一定程度上是安全的。
  4. 用户观察验证码,手动输入内容,最后将账号、密码、验证码一起发送到后端进行认证。
  5. 后端将客户端发送过来的验证码和 Session 中的验证码进行对比,一致后才验证账密的有效性。
用户请求验证码
后端生成随机字符
生成验证码图片
保存随机字符串到Session
返回验证码图片给前端
前端展示验证码图片
用户观察并输入验证码
前端发送账号、密码、验证码
后端验证验证码
验证码一致?
验证账密有效性
验证码错误,重试
认证成功/失败

那么验证账号密码的流程是什么样的呢?

  1. 首先通过账号密码查询数据库 user 表中是否有对应的记录。
  2. 如果没有记录,则有两种可能,一种是用户不存在,另一种是账号或密码输错了。但是为了不给用户留下猜测的空间,错误提示语都用统一的“用户名或密码输入有误”。
  3. 如果有记录,说明账号密码正确,此时更新这条 user 记录,用 Session ID 更新 token 字段。
  4. 将脱敏的用户信息返回给前端,同时 Set-Cookie 更新 cookie 中的 token 信息。
res.cookie('token',req.session.id,{expires: expireTime,httpOnly: true,sameSite: 'lax',secure: true}
);
无记录
有记录
用户输入账号密码
查询user表记录
返回:用户名或密码输入有误
账号密码正确
更新user记录token字段为Session ID
返回脱敏用户信息
Set-Cookie更新cookie中的token信息
流程结束

权限设计的具体实现

我们知道,有的接口是需要鉴权的,只有管理员能访问,而有的接口是开放的,人人都能访问,这就需要权限的设计。

我们的博客系统中暂时还只有一个管理员账号,按这个设定,我们可以认为:如果 Cookie 中的 token 校验通过,就认为这个用户是管理员账号,可以访问需要鉴权的接口。

但是这并非一个优雅的设计,RBAC(Role-based access control)是一种更容易扩展的方式。我们还是预留了用户/角色/权限的关系。

通过用户的 role_id,我们能关联查询到这个用户的角色,基于角色,再去找到这个用户的权限。

image.png

由于目前,博客系统中用到的权限管理只涉及到接口权限,这里我就没有过度设计了,直接把接口权限和角色的关系写死在后端代码里。

image.png

PS: 这里用 Map 还是用什么数据结构不是很重要,能对应上角色和权限的关系更重要…

访问链路分析

知道角色和权限的关系后,我们再来完整看看不需要鉴权的接口需要鉴权的接口走过的链路分别是什么样的?

我们来到后端代码的 base.js 控制器,这是验证权限的入口。一个接口是否要验证权限,暂时是维护在前面提到的 authMap 中,如果以 req.path(也就是接口请求路径)作为 key 能在 authMap 中找到值,说明这是一个需要验证权限的接口。

如果在 authMap 中找不到对应的值,说明这个接口是不需要鉴权的,base 控制器直接放行请求即可。

如果一个接口需要验证权限,会首先取出 Cookie 中的 token,查数据库 user 表。

如果没找到记录(也就是下图中的 results.length === 0 这个条件),可以考虑返回前端“授权已过期”或者“未授权”之类的信息。

如果 token 是有效的,还需要验证 user 信息中的 role_name 是否和该接口限制的角色一致。

如果不一致,说明该用户不具备这个接口的访问权限,返回前端“抱歉,您没有权限访问该内容”这样的信息即可。

如果一致,说明该用户有这个接口的访问权限,把执行权交给后续中间件即可。

image.png

博客后台管理类接口只有管理员能访问,这些是需要鉴权的。

image.png

首页的文章分页数据是所有访问者都能查看的,这就是一个典型的不需要鉴权的接口。

image.png

小结

博客系统中,对于游客而言,可以查看文章、留言等开放性的数据;对于管理员而言,还需要管理后台功能来维护文章、审核评论等,这就需要一个登录认证的能力。在 Web 项目中,常用的认证方案就是基于 Cookie + Session 的认证。有了登录认证后,其实还应该根据角色去区分用户的权限,虽然本系统中只有一个管理员存在,但是我们还是预留了 RBAC(Role-based access control) 的能力。

码字分享不易,多多点赞关注,项目给个 star,多谢啦,宝子!

  • 开源地址:vue3-ts-blog-frontend
  • 专栏导航:Vue3+TS+Node打造个人博客(总览篇)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3250108.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

宋仕强谈狼性营销与五看三定

宋仕强说余承东董宇辉联合宣传,他们的狼性营销我们要学习,我们金航标和萨科微要认真学习华为的先进理念和成功经验,和“五看三定”思维和工作模型,让管理团队深度思考,再不断实践。在产品定义和市场定位方面&#xff0…

小程序js 把链接转换为二维码

GitHub - Rookie-M/weapp-qrcode: weapp.qrcode.js 在 微信小程序 中,快速生成二维码 1.要下载上面地址的插件包 2.引用 import drawQrcode from ../../utils/weapp.qrcode.minonLoad(options) {let that thisconsole.log(JSON.parse(options.info))that.setData…

Ubuntu 24.04 LTS 桌面安装MT4或MT5 (MetaTrader)教程

运行脚本即可在 Ubuntu 24.04 LTS Noble Linux 上轻松安装 MetaTrader 5 或 4 应用程序,使用 WineHQ 进行外汇交易。 MetaTrader 4 (MT4) 或 MetaTrader 5 是用于交易外汇对和商品的流行平台。它支持各种外汇经纪商、内置价格分析工具以及通过专家顾问 (EA) 进行自…

【BUG】已解决: KeyboardInterrupt

已解决: KeyboardInterrupt 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页,我是博主英杰,211科班出身,就职于医疗科技公司,热衷分享知识,武汉城市开发者社区主理人 擅长.net、C…

折叠屏遇上Galaxy AI,三星新一代Galaxy Z系列开启移动终端新篇章

作者 | 曾响铃 文 | 响铃说 随着换机周期的普遍延长以及智能手机行业内竞争态势的日益激烈,传统的硬件升级与参数比拼已难以全面满足消费者日益多元化的需求。面对这一挑战,行业迫切需要探索新的增长路径与发展方向。 折叠屏技术的兴起,无…

npm install时报错 reason: certificate has expired

在VS code中导入新项目,执行npm install时报错: npm warn old lockfile Could not fetch metadata for antv/g3.4.10 FetchError: request to https://registry.npm.taobao.org/antv%2fg failed, reason: certificate has expirednpm warn old lockfile …

用DrissionPage过某里滑块分析

最近我又在找工作了,悲哀啊~,面试官给了一道题,要求如下: 爬虫机试:https://detail.1688.com/offer/643272204627.html 过该链接的滑动验证码,拿到正确的商品信息页html,提取出商品维度的信息&a…

Notepad++换安装路径之后,右键打开方式报错:Windows无法访问指定设备、路径或文件。你可能没有适当的权限访问该项目。的处理方法

把Notepad添加到右键打开方式,可以参考下面的3篇文章添加: https://blog.csdn.net/xiaoerbuyu1233/article/details/88287747 https://blog.csdn.net/qq_44000337/article/details/120277317 https://www.cnblogs.com/zhrngM/p/12899026.html 这里主要是…

docker安装mysql突然无法远程连接

docker安装mysql突然莫名其妙的无法远程连接 docker安装mysql突然无法远程访问问题背景发现问题排查问题解决问题总结 docker安装mysql突然无法远程访问 问题背景 大概一年前在服务器中通过docker安装mysql5.7端口映射关系是3308->3306 前期在服务器上开方了3308端口 fir…

redis操作set时的性能分析y以及一系列问题

redis操作set时的性能分析y以及一系列问题 第一次测试 初始状态 第一次测试 第二次 初始状态 第二次测试 测试代码 Javapackage cn.only.hww; import redis.clients.jedis.Jedis; import java.util.*;/** * author…

液氮罐搬运过程中的安全注意事项有哪些

在液氮罐搬运过程中,安全性是至关重要的考虑因素。液氮是一种极低温的液体,其温度可达零下196摄氏度,在接触到人体或物体时会迅速引发严重的冷冻伤害。因此,正确的搬运和使用液氮罐是保障操作安全的关键。 液氮是一种无色、无味的…

每日一题,力扣leetcode Hot100之128. 最长连续序列

题目理解: 从示例1可以看出简单的连续数字就算,从示例2可以看出当有重复数字时,是不算长度的 解法一: 第一个想到的解法,就是对nums排序,然后双层循环遍历进行判断,当前一个和后一个相减等于…

【鸿蒙学习笔记】位置设置・direction・容器内主轴方向上元素的布局

官方文档:位置设置 目录标题 direction・容器内主轴方向上元素的布局Row direction direction・容器内主轴方向上元素的布局 Row direction Row() {Text(1).height(50).width(25%).fontSize(16).backgroundColor(0xF5DEB3).textAlign(TextAlign.Center)Text(2)…

NVidia 的 gpu 开源 Linux Kernel Module Driver 编译 安装 使用

见面礼,动态查看gpu使用情况,每隔2秒钟自动执行一次 nvidia-smi $ watch -n 2 nvidia-smi 1,找一台nv kmd列表中支持的 GPU 的电脑,安装ubuntu22.04 列表见 github of the kmd source code。 因为 cuda sdk 12.3支持最高到 ubu…

[MySQL][索引][下][理解索引]详细讲解

目录 0.前期准备1.为何IO交互要是Page?2.理解单个Page3.理解多个Page4.页目录5.单页情况6.多页情况7.总结复盘8.InnoDB 在建立索引结构来管理数据的时候,其他数据结构为何不行?9.聚簇索引 vs 非聚簇索引 0.前期准备 建立测试表 create table …

网站开发:使用VScode安装yarn包和运行前端项目

一、首先打开PowerShell-管理员身份运行ISE 输入命令: set-ExecutionPolicy RemoteSigned 选择“全是”,表示允许在本地计算机上运行由本地用户创建的脚本,没有报错就行了 二、接着打开VScode集成终端 输入 npm install -g yarn 再次输入以…

2-38 基于matlab的蚁群算法优化无人机uav巡检

基于matlab的蚁群算法优化无人机uav巡检,巡检位置坐标可根据需求设置,从基地出发,返回基地,使得路径最小。可设置蚁群数量,信息素系数。输出最佳路线长度。程序已调通,可直接运行。 2-38 蚁群算法优化无人…

人工智能算法工程师(高级)课程1-单类目标识别之人脸检测识别技术MTCNN模型介绍与代码详解

大家好,我是微学AI,今天给大家介绍一下人工智能算法工程师(高级)课程1-单类目标识别之人脸检测识别技术MTCNN模型介绍与代码详解。本文深入探讨了基于PyTorch的人脸检测与识别技术,详细介绍了MTCNN模型、Siamese network以及center loss、sof…

Linux/Windows 系统分区

1. Windows 系统 1.1 系统分区 系统分区也叫做磁盘分区,即分盘; 举个例子,好比家里有一个大柜子,把衣服,鞋子,袜子都放在里面,由于没有隔断,找的时候非常麻烦,找是能找…

ETL数据集成丨通过ETLCloud工具,将Oracle数据实时同步至Doris中

ETLCloud是一个全面的数据集成平台,专注于解决大数据量和高合规要求环境下的数据集成需求。采用先进的技术架构,如微服务和全Web可视化的集成设计,为用户提供了一站式的数据处理解决方案。 主要特点和功能包括: 实时数据处理&…