扫码登录+反向代理鉴权

背景wushf.top下挂载的服务会越来越多,大多数服务是拉取自第三方仓库。导致每个服务都有自己的鉴权方式,需要维护多套密码。原作者未必为自己的项目提供单点登录的接口,需要自己考虑解决方案,暂行的方案是:自己开发单点登录,通过SetCook

扫码登录+反向代理鉴权

背景

wushf.top下挂载的服务会越来越多,大多数服务是拉取自第三方仓库。

导致每个服务都有自己的鉴权方式,需要维护多套密码。

原作者未必为自己的项目提供单点登录的接口,需要自己考虑解决方案,暂行的方案是:

  • 自己开发单点登录,通过SetCookie为合法用户授权。

小程序登录方案

常见的解决方案是提供一个正方形的标准二维码,扫码登陆。

但是这个要多方备案,还要认证成个体工商户或者企业,需要交钱,比较麻烦。

暂行的方案是:

  • 扫小程序码,在小程序中与后端通信,实现鉴权登录。

登录流程

网页端请求生成新的小程序二维码

根据官方文档,可以携带一个scene

生成一个sessionId作为会话的唯一标识,将会话作为scene加入到微信小程序二维码中。

  • 手机扫码解析得到sessionId,就知道了“我要授权哪个会话”。

二维码有扫描状态,被一个用户扫描之后应不能再被其他用户扫描。

  • 手机扫码时应检查是否已被其他用户扫码。

网页轮询当前会话的状态,如已被扫描,那么登录成功,跳转到下一级页面。

这只是大概思路,授权涉及系统的安全性,目前开放的code服务会允许用户借助code-server服务修改开发机文件,因此必须要做好鉴权。

不碰撞地生成sessionId

生成sessionId,有一个经典的解决方案,就是生成随机数,检查是否已经存在,若已存在,那么重新生成。

这种方法大概率是没问题的。

但是还是实现了一个无碰撞的生成方案。

观察到一个凭证只在短时间内有效,目前设置的是时长2min的滑动窗口。

那么2min之前生成的凭证,已经在Redis中过期了,不需要再判断有没有碰撞。

可以取当下的时间戳,用2min取模,模数恰好是6位。

代码中目前用的是3min,做一下滑动窗口长度的冗余。

阻止未经授权的查询

sessionId是一个六位的数字,是不是可以暴力枚举,查询服务器所有会话的状态。

这样显然是不安全的。

在向浏览器传递sessionId时,携带Jwt作为auth凭证。

只有Jwt的负载部分与sessionId匹配时,才允许访问。

阻止未经授权的授权

期望是有权限的用户才有权限授权。

利用SpringSecurity,在对访问鉴权之后,会在上下文存储权限列表。

可以在下文直接取出。

如果权限列表没有我需要的权限,那么阻止授权。

Spring端设计

考虑到未来会扩展更多的服务,需要配置不同的权限,所以授权页面也做了对未来的支持。

在路径中传入申请的权限,在登录时阻止无权用户。

考虑到有权用户未来可能无权,也需要阻止。

权限维护在数据库中,请求服务的时候还是再次验证。

SetCookie传递会话凭证

Redis中也塞入了sessionIdtoken的临时绑定关系,做了二次验证。

获取会话状态

用户的凭证和浏览器的凭证格式是不一样的。

当用户查询状态时,如果是第一个用户,那么说明该用户手机扫码了,才能知道这个sessionId并授权。

  • 不需要额外的外部接口供修改二维码状态到已扫描
  • 用户查询的时候,就已经扫描了。

浏览器查询时,通过凭证验证身份,必须和当前会话一致才能查询。

为NGINX提供鉴权接口

这个比较简单粗暴。

能通过SpringSecurity,走到这一步,一定是凭证合法的。

验证当前用户的权限列表。有权则允许访问。

数据库维护权限分配

简单解耦:权限变更不需要重新编译代码。

Vue端设计

原计划是搞个导航栏,搞个弹窗的,搞几个用户管理的页面的。

然后发现现在的服务接口有点少,很少有权限操作,上号用数据库也够用。

所以撤回了导航栏和弹窗,只保留了登录界面。

个人觉得外观还是挺现代化的,登录即是授权:

弹窗中鉴权

未来的增长点之一。

创建一个全局的弹窗容器,在需要时填入组件。

容器是否显示,内部填充哪个组件,等等状态,通过pinia维护并在组件间通信。

动画效果优化

亲测如果没有动画,会等待两秒办然后出现,比较丑陋。

让GPT生成了一个加载动画,一个转圈的圆形:

为图片加了个透明度过渡动画,图片准备完成后渐显。

小程序端设计

初始方案是TS基础模板。

发现兼容性太差了,微信开发者工具提供的初始模板,里面好多语法已经被微信官方弃用了,顶部导航栏在不同设备上高度还不一样。

而且类型检查很差,我也不知道在微信小程序中应该定义成什么类型,是否已被弃用。

最终用的是JS+Sass

Canvas画圈

小程序功能比较简单。

加了个渐变的圆反馈状态。

想动态修改圆的颜色和速度,发现纯css有点困难,小程序的语法兼容性问题有点难搞。

最后改成了canvas画圆。

但是canvas会强制处于最高层,无论其他组件设置多少z-index。所以画圆的时候还要画个字母。

扫码状态验证

前文提到,首个用户扫码会自动修改状态为已扫描。

如何判断是不是当前用户,就看Jwt负责部分是不是自己。

因为Jwt凭证的前两个部分header都是明文转Base64

Base64转回JSON字符串就可以。

比较坑的是aotb在微信开发者工具中能用,手机上不能用。

代码语言:javascript代码运行次数:0运行复制
export const atobPolyfill = (base64) => {
  var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  var output = '';
  var buffer = 0;
  var bitCount = 0;
  for (var i = 0; i < base64.length; i++) {
    var char = base64.charAt(i);
    if (char === '=') break;

    buffer = (buffer << 6) | chars.indexOf(char);
    bitCount += 6;

    if (bitCount >= 8) {
      bitCount -= 8;
      output += String.fromCharCode((buffer >> bitCount) & 0xFF);
      buffer &= (1 << bitCount) - 1;
    }
  }
  return output;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2025-04-13,如有侵权请联系 cloudcommunity@tencent 删除反向代理服务权限小程序登录

发布者:admin,转转请注明出处:http://www.yc00.com/web/1747718285a4685532.html

相关推荐

  • 扫码登录+反向代理鉴权

    背景wushf.top下挂载的服务会越来越多,大多数服务是拉取自第三方仓库。导致每个服务都有自己的鉴权方式,需要维护多套密码。原作者未必为自己的项目提供单点登录的接口,需要自己考虑解决方案,暂行的方案是:自己开发单点登录,通过SetCook

    13小时前
    10

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信