Express实战个人订阅号实现网站登录

时间:2023-05-18 16:33:26 来源: 博客园

今天我们来实现一个使用个人订阅号实现网站的功能,后端使用的是 express。其它框架原理基本一致,只是定义路由或返回响应数据部分代码跟 express有所出入。先来一波效果图:


(资料图片)

1. 前言

20 年 3 月在掘金写过一篇文章,介绍了使用 express开发微信公众号的案例: 原文地址。当时使用的 nodejs版本还是 v8.x,现如今,nodejs的最新长期稳定版已经来到了 v18.16.0, 新特性尝鲜版更是已经到了 v20.1.0

不得不感慨时间之飞逝,nodejs 的版本升级之路见证了技术的飞速进步,也见证了我发际线的飞速退后。

......

2. 为何要用订阅号去登录

看了看掘金,发现掘金的登录注册分为两种:

手机号验证码注册第三方登录(支持微信扫码、微博、Github)

企业站来说,这种方式固然好,给了用户提供了更多的选择。

但是对于个人站点,这种方式就不太友好了,因为:

手机号接收验证码注册:1 条短信 1 毛钱,10 条就是 1 块,100 条就能吃个豪华早餐了

接入微信开放平台是需要企业资质的。我一个打工人,上哪儿去搞企业资质?这就是一道坎,更别说后续接入的繁琐流程了。

Github 倒是不需要,不过接入也麻烦,弃之!

微博?用户没有微博账号是不是还得去注册个微博账号?弃!

那就普通的注册吧?填写用户名、密码、确认密码、输入邮箱,邮箱验证码确认?弃!

那么,它来了!订阅号注册免费,花极少的时间去接入

用户只需关注公众号,反手输入个登录,回车!Ctrl + CV。欸,很快啊,登录成功!

相对于传统的注册填一大堆资料 + 确认密码 + 验证码,孰好孰坏,熟快熟慢,一试便知。

而且,且看下图,它对于保护用户隐私来说,是极好的,因为开发者只能拿到用户的 OpenID,头像和昵称都不给你!

不过, 有 OpenID就足够了,毕竟它对于当前公众号来说,是 唯一的

3. 公众号后台配置

完整的接入指南详见: https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html

进入微信公众平台

设置与开发 -> 基本配置 -> 公众号开发信息 -> IP 白名单中配置你的服务器 IP

设置与开发 -> 基本配置 -> 服务器配置(未开启的需要先开启)

URL是你的后端服务对应验证授权的接口地址,也就是你后端服务部署后绑定了域名的接口地址。举例: https://www.xxx.com/wechat

Token这块的 Token按照平台提示的规则自定义即可,注意,需要和上面代码中的 Token相对应,不然会验证不成功。

EncodingAESKey是消息加解密密钥,这个可以随机生成,也可以自定义

消息加解密方式选择明文模式即可

填写好上面这些内容之后,我们先不必急着点击提交,因为这个时候服务还没部署,服务器是无法正常响应微信服务器的验证请求,必然会提交失败。

且看下文

4. 登录流程梳理

我们简单的梳理一下登录流程:

首先是需要在网站需要登录的地方,放置一个公众号的二维码,并用醒目的文字给用户提示:关注公众号后发送 "登录" ,获取登录所需要的验证码

后台接收到用户请求,判断用户发送的内容的确是 "登录" 关键字,返回一个验证码给用户,并将当前验证码存起来

用户输入验证码,后台根据存起来的验证码进行验证,验证成功,返回登录成功,否则,登录失败

5. 定义服务端路由,处理验证逻辑及服务端部署5.1 定义授权验证接口

主要是验证消息的确来自微信服务器

import express from "express";import jsSHA from "jssha";const router = express.Router();router.get("/wechat_mp", (req, res, next) => {  const token = "这里是自定义Token,可自定义,内容规则详见下文";  //1.获取微信服务器Get请求的参数 signature、timestamp、nonce、echostr  const { signature, timestamp, nonce, echostr } = req.query;  //2.将token、timestamp、nonce三个参数进行字典序排序  const array = [token, timestamp, nonce].sort();  //3.将三个参数字符串拼接成一个字符串进行sha1加密  const tempStr = array.join("");  const shaObj = new jsSHA("SHA-1", "TEXT");  shaObj.update(tempStr);  const scyptoString = shaObj.getHash("HEX");  //4.开发者获得加密后的字符串可与signature对比,标识该请求来源于微信  if (signature === scyptoString) {    console.log("验证成功");    res.send(echostr);  } else {    console.log("验证失败");    res.send("验证失败");  }});
5.2 处理用户 "登录" 消息

接下来我们定义用户发送消息的逻辑:

当用户发送文本消息给公众号的时候,微信服务器会将用户发送的消息以 XML格式的参数去请求这个接口,只不过这个时候,我们需要通过 POST请求来接收参数。

先上代码:

定义POST接口

import { parseString } from "xml2js";import myCache from "../store";/** * 随机6位验证码 */function randomCode() {  return Math.random().toString().slice(-6);}/** * 回复文字消息封装 */function sendTextMsg(toUser, fromUser, content) {  let resultXml = "";  resultXml += "";  resultXml += "" + new Date().getTime() + "";  resultXml += "";  resultXml += "";  return resultXml;}router.post("/wechat_mp", function (req, res) {  var buffer = [];  req.on("data", function (data) {    buffer.push(data);  });  // 内容接收完毕  req.on("end", function () {    var msgXml = Buffer.concat(buffer).toString("utf-8");    parseString(msgXml, { explicitArray: false }, function (err, result) {      if (err) throw err;      result = result.xml;      const { ToUserName, FromUserName, MsgType, Content } = result;      if (MsgType === "text" && Content === "登录") {        const code = randomCode();        // 这里的FromUserName就是用户的OpenID        myCache.set(code, FromUserName, 1 * 60 * 5);        const sendXml = sendTextMsg(          ToUserName,          FromUserName,          `您的登录验证码是:${code}  ,  有效期为5分钟`        );        res.send(sendXml);      }    });  });});

store/index.js

import NodeCache from "node-cache";const myCache = new NodeCache();export default myCache;

代码解释:

XML 解析:可以通过安装 xml2js这个库来解析 XML格式的参数

接化发:检测到用户发送 消息类型text且内容为 登录关键字的时候,我们去生成一个 6位随机验证码,再将验证码和用户的 OpenIDkey(code)、value(OpenId)的格式存入 存入 node-cache中,并设置有效期为 5分钟,同时将随机验证码发送给用户。

5.3 处理网站登录逻辑

上一步,用户已经在微信公众号上获取到了随机验证码,现在只需要在网站需要登录的地方输入验证码,调用验证码校验接口即可进行校验。

定义验证码校验接口

import myCache from "../store";router.get("/verify", async function (req, res) {  const { code } = req.query;  const OpenID = myCache.get(code);  if (OpenID) {    const token = "使用OpenID进行jwt鉴权颁发Token";    res.json({      code: 200,      data: { token },    });  } else {    res.json({      code: 400,      msg: "您输入的验证码有误或已过期,请重新输入!-_-",    });  }});

代码解释:

根据用户输入的验证码,去 node-cache中获取 OpenID,如果存在,则说明验证码正确,jwt鉴权颁发 Token。反之,校验失败。

验证码校验成功后,通过唯一的 OpenID和自定义的 secret给用户颁发 Token,用户再次访问网站的时候,只需要携带 Token即可进行鉴权。

关于 jwt鉴权概念、流程及使用,大家可以参考这条 AI 问答分享:

我在ChatGPTer(https://ai.iiter.cn)网站上创建了一个AI对话分享,快来看看吧!「jwt鉴权概念、流程」链接:https://ai.iiter.cn/#/share/6465c5a2e82a696c417bbfa9

同时,也欢迎大家自己进行 AI 问答: https://ai.iiter.cn

5.4 部署服务

服务部署这块大家可以参考我之前写的一篇傻瓜式部署文章:宝塔面板结合 pm2 进程管理工具部署前端项目

当然,您也可以使用自己顺手的部署方式

5.5 提交公众号配置

服务部署成功后,回到我们的 公众号后台配置部分,点击提交即可

结语

至此,我们的个人订阅号登录功能就已经完成了,相信基于以上,大家都可以很快的去做出一个网站登录功能出来

而且在给用户提供服务的同时,可以直接将用户引导至自己的公众号上。不管是后面对网站的更新记录,还是一些重要的通知,都可以通过公众号进行消息推送,一举两得

好了,今天的文章分享就到这里了,如果对大家有所帮助的话,希望您不要吝啬手中的赞呦~

正式给大家介绍一下:

基于 OpenAIAPI开发的一款 ChatGPT网站,模型是gpt-3.5-turbo,使用的是本篇文章的同款登录方式,欢迎大家体验

免费!免费!免费!https://ai.iiter.cn

标签:

精彩推送

倒车入库技巧视频 新手必看科目二_倒车入库技巧视频|世界百事通

你们好,最近小未来发现有诸多的小伙伴们对于倒车入库技巧视频新手必看科目二,倒车入库技巧视频这个问题都

来源:2023.05.15

天气转热烫伤高发 专家支招“冲脱泡盖送”处理

烧伤、烫伤是平时生活中非常常见的意外伤害。随着夏天的到来,人们衣着相对单薄,外露的体表面积大大增加,

来源:2023.05.15

【世界时快讯】强如直六发动机还要刷ECU?宝马740Li B58特调动力D挡堪比S挡!

德系豪华三驾马车BBA的领域里,3 0T6缸发动机都是非常顶尖的水平,其中宝马从N55到现在的B58一直在坚持使用

来源:2023.05.15

世界新资讯:扣非净利连亏两年 睿智医药大股东违规减持被问询

《投资者网》张伟众所周知,证监会对上市公司股东减持程序及信息披露义务都有明确规定。不过,也有一些A股

来源:2023.05.15

2023年5月13日雅思阅读考试题答案

2023年5月13日雅思阅读考试已经结束,来和小编一起看看本场雅思阅读的题型和答案吧。

来源:2023.05.15

欠银行多少钱会被起诉?信用卡逾期怎么办?

欠银行多少钱会被起诉?1、欠银行信用卡时间久了肯定是会被银行起诉的,一般来说故意拖欠银行五千元以上

来源:2023.05.15

昆山对降价房企进行处罚:托市乎,维稳乎?丨快评

2023年5月5日,昆山住建局在微信群发布的一则《通报文件》引发关注。因为“擅自大幅度降价销售,扰乱了...

来源:2023.05.15

世界新动态:15省区市加力扩需求,文旅消费提升空间大

每经AI快讯,今年以来,接触型、出行类服务快速回暖。人民银行公布的一季度城镇储户调查问卷结果显示,未来

来源:2023.05.15

f4v是什么格式的视频(f4v是什么格式)

1、首先我们打开浏览器,输入视频转换功能的网址,进入在线格式转换功能页面。2、进入视频转换页面后,我们

来源:2023.05.15

新闻快讯

X 关闭

X 关闭

新闻快讯