白日放歌须纵酒,青春作伴好还乡。这篇文章主要讲述巧用云函数打造微信网页授权公用服务相关的知识,希望能为你提供帮助。
背景
公司为客户开发微信公众号相关服务时,有时未能准备好公众号,所以需要使用公司的公众号,但是大家都知道微信网页授权域名最多只支持两个,这就造成了如果有多个项目需要同时开发时产生了如下问题:
- 网页授权地址不够用
- 公众号不够用
- 某功能比如微信快捷登录突然失效(授权地址被改掉)
关于域名占用的问题,其实在
github
上已经有现成的方法了,可以实现多域名的授权,而且实现内容也比较简单,就是一个粗暴的静态html
文件去处理授权用的参数。博主之前曾经做过一个网页授权扫码登录的Demo
就用到了这个静态文件。正常情况下如果用到了网页授权获取用户信息,一般是需要一台服务器一个备案过的域名的,那么如果没有服务器改咋整呢?
云函数很巧妙地解决了这个问题,我们只需要一个自己的域名(不用其实也可以)就可以通过云函数来托管这个授权用的文件来实现通用的授权服务。
下面我们来看一下如何去做这么一个简易的基础服务。
需求分析
【巧用云函数打造微信网页授权公用服务】首先我们知道配置网页授权域名的时候需要在公众号添加这个域名,要求我们在服务器上上传一个验证文件,并且这个文件要挂在根目录下才可以访问到,这就要求我们增加一个文件上传的功能。
这种情况下云函数就需要具备如下能力:
- 静态文件托管
txt
验证文件上传
实现步骤
应用创建在云函数的后台直接创建应用,使用koa模板。
文章图片
应用修改应用创建好之后会在云函数列表里出现名为
koa-starter
的函数,我们需要修改这个函数的代码。应用模板的源码在github上就可以获取-> koa-starter。
这里讲解一下几个核心修改的实现吧:
app.js
内增加文件上传的支持,小文件是可以直接上传的。
app.use(
koaBody({
multipart: true,
formidable: {
multipart: true,
maxFileSize: 400 * 1024 * 1024 // 设置上传文件大小最大限制,默认4M
}
})
)
- 然后增加一些全局的处理
// 全局异常处理
app.use(async (ctx, next) =>
{
try {
await next()
} catch (err) {
ctx.body = {
code: -1,
data: ctx.data,
message: ctx.msg || err.message || 服务开小差了,请稍后再试,
etime: Date.now()
}
}
})// pretty json result
app.use(async (ctx, next) =>
{
await next()
if (ctx.data) {
ctx.set(Content-Type, application/json)
ctx.body = {
code: ctx.code || 0,
data: ctx.data,
message: ctx.msg || success,
etime: Date.now()
}
}
})
- 在
routes/index.js
中增加上传文件的路由处理
router.post("/uptxt", async (ctx, next) =>
{
if (!ctx.request.files) {
ctx.data = https://www.songbingjia.com/android/未选择文件
await next()
return
}
// 获取上传文件
let file = ctx.request.files.file
// 创建可读流
let reader = fs.createReadStream(file.path)
let filePath = `/tmp/${file.name}`// 创建可写流
const upStream = fs.createWriteStream(filePath)
await reader.pipe(upStream);
ctx.data = file.name
ctx.code = 0
ctx.msg = 上传验证文件成功
await next()
});
- 前端的模板目录
views
下面增加两份页面代码。auth.html
文件,用于授权处理,代码参考。up.html
文件,用于文件上传。
- 云函数在执行过程中,都拥有一块500MB的临时磁盘空间 /tmp,用户可以在执行代码时对该空间进行一些读写操作,也可以创建子目录,但这部分数据在函数执行完成后不会保留。
解决办法当然是有的,那就是手动修改静态资源目录为tmp。
修改app.js文件:
app.use(require(koa-static)(/tmp))
这样在上传之后就可以直接访问到了。
- 首页及上传页的路由处理:
router.get("/", async (ctx, next) =>
{
await ctx.render("index");
});
router.get("/up", async (ctx, next) =>
{
await ctx.render("up");
});
- 授权页的访问路由处理:
router.get("/auth.html", async (ctx, next) =>
{
await ctx.render("auth");
});
- 保存代码并配置访问服务。
文章图片
vue项目为例
插件引入:
在项目中加入生成回调地址的
wechatAuth.js
文件。部分代码参考:
// 引入插件
import wechatAuth from @/plugins/wechatAuth// 设置APPID
wechatAuth.setAppId(process.env.VUE_APP_WECHAT_APPID)// 使用插件生成授权回调地址
wechatAuth.redirect_uri = processUrl()/**
* 处理url链接
* @returns {string}
*/
function processUrl() {
// 本地环境拿code
if (process.env.NODE_ENV === development) {
// 中间授权页地址
return `${process.env.VUE_APP_WECHAT_AUTH_URL}?backUrl=${window.location.href}`
}
const url = window.location.href
// 解决多次登录url添加重复的code与state问题
const urlParams = qs.parse(url.split(?)[1])
let redirectUrl = url
if (urlParams.code &
&
urlParams.state) {
delete urlParams.code
delete urlParams.state
const query = qs.stringify(urlParams)
if (query.length) {
redirectUrl = `${url.split(?)[0]}?${query}`
} else {
redirectUrl = `${url.split(?)[0]}`
}
}
return redirectUrl
}
环境变量配置:
#appid 可填入申请的测试公众号id或者其它准备好的ID
VUE_APP_WECHAT_APPID=#authUrl 网页授权中间页
VUE_APP_WECHAT_AUTH_URL=云函数http访问服务地址/auth.html
整个授权服务的流程可概括为下图:
文章图片
因为我们只是把获取微信授权code的过程统一放到了云函数去处理,所以多个项目在调试时都可以使用同一个地址,减少了资源占用,不失为一个可用方案。
我们仅需要一个云函数就可以实现微信授权的本地调试以及几个项目几个公众号共用一个授权服务,免去独立域名、独立服务器的烦恼。
服务Demo演示
这里提供了一个云函数网页授权服务的Demo地址:
http://cloud.xuedingmiao.com/
文章图片
参考资料
- koa-starter 应用模板代码
- 通用问题-云函数可写空间
- 网页授权应用案例
原文地址:http://xuedingmiao.com/blog/scf_wx_page_auth_service.html
推荐阅读
- 微服务架构中,二次浅封装实践
- Flutter 专题15 图解 ListView 异步加载数据与等待#yyds干货盘点#
- 一个普通的开发日常-记一次缓存问题在实际开发中的解决方案
- flutter 中的列表的性能优化前奏#yyds干货盘点#
- #聊一聊WuKong编辑器#7 赞 6 建议 5 改进
- 02~文件通配符用户及用户组
- linux之拖拽上传文件
- #yyds干货盘点# Golang Gin 框架上传介绍
- oeasy教您玩转vim - 67 - # 批量替换