Go+gRPC-Gateway(V2) 微服务实战,小程序登录鉴权服务(六):客户端基础库 TS 实战

小程序登录鉴权服务,客户端底层 SDK,登录鉴权、业务请求、鉴权重试模块 Typescript 实战。
系列
- 云原生 API 网关,gRPC-Gateway V2 初探
- Go + gRPC-Gateway(V2) 构建微服务实战系列,小程序登录鉴权服务:第一篇
- Go + gRPC-Gateway(V2) 构建微服务实战系列,小程序登录鉴权服务:第二篇
- Go + gRPC-Gateway(V2) 构建微服务实战系列,小程序登录鉴权服务(三):RSA(RS512) 签名 JWT
- Go+gRPC-Gateway(V2) 微服务实战,小程序登录鉴权服务(四):自动生成 API TS 类型
- Go+gRPC-Gateway(V2) 微服务实战,小程序登录鉴权服务(五):鉴权 gRPC-Interceptor 拦截器实战
Demo: go-grpc-gateway-v2-microservice
前端底层初步搭建(SDK)
新建 client/miniprogram/service/sdk.ts 文件,来初步搭建一下我们前端的底层公共设施。
定义一个 SDK namespace
export namespace SDK {
}
定义相关常量 & Interface
const serverAddr = 'http://localhost:8080'
const AUTH_ERR= 'AUTH_ERR'
const authData = {
token: '',
expiryMs: 0
}
interface RequestOption<REQ, RES> {
method: 'GET'|'PUT'|'POST'|'DELETE'
path: string
data: REQ
respMarshaller: (r: object)=>RES
}
interface AuthOption {
attachAuthHeader: boolean
retryOnAuthError: boolean
}
这里主要根据当前需求,做了如下事情:
- 抽出服务器地址
serverAddr - 定义一个授权失败
401常量 token相关暂时存到内存中- 定义客户端
wx.request所必须的参数类型 - 控制授权请求相关逻辑(是否附加
Auth Header& 重试等)
wx.login 改写成 Promise 形式
export function wxLogin(): Promise<WechatMiniprogram.LoginSuccessCallbackResult> {
return new Promise((resolve, reject) => {
wx.login({
success: resolve,
fail: reject,
})
})
}
请求公共逻辑 wx.request 编写
export function sendRequest<REQ, RES>(o: RequestOption<REQ, RES>, a: AuthOption): Promise<RES> {
const authOpt = a || {
attachAuthHeader: true,
}
return new Promise((resolve, reject) => {
const header: Record<string, any> = {}
if (authOpt.attachAuthHeader) {
if (authData.token && authData.expiryMs >= Date.now()) {
header.authorization = 'Bearer '+ authData.token
} else {
reject(AUTH_ERR)
return
}
}
wx.request({
url: serverAddr + o.path,
method: o.method,
data: o.data,
header,
success: res => {
if(res.statusCode === 401) {
reject(AUTH_ERR)
} else if (res.statusCode >= 400) {
reject(res)
} else {
resolve(
o.respMarshaller(
camelcaseKeys(res.data as object, { deep: true }),
)
)
}
},
fail: reject
})
})
}
登录模块(login)编写
export async function login() {
if (authData.token && authData.expiryMs >= Date.now()) {
return
}
const wxResp = await wxLogin()
const reqTimeMs = Date.now()
const resp = await sendRequest<auth.v1.ILoginRequest, auth.v1.ILoginResponse>({
method: "POST",
path: "/v1/auth/login",
data: {
code: wxResp.code,
},
respMarshaller: auth.v1.LoginResponse.fromObject
}, {
attachAuthHeader: false,
retryOnAuthError: false,
})
authData.token = resp.accessToken!
authData.expiryMs = reqTimeMs + resp.expiresIn! * 1000
}
业务请求自动重试模块编写
export async function sendRequestWithAuthRetry<REQ, RES>(o: RequestOption<REQ, RES>, a?: AuthOption): Promise<RES> {
const authOpt = a || {
attachAuthHeader: true,
retryOnAuthError: true,
}
try {
await login()
return sendRequest(o, authOpt)
} catch(err) {
if(err === AUTH_ERR && authOpt.retryOnAuthError) {
authData.token = ''
authData.expiryMs = 0
return sendRequestWithAuthRetry(o, {
attachAuthHeader: authOpt.attachAuthHeader,
retryOnAuthError: false
})
} else {
throw err
}
}
}
Todo Service
客户端具体服务层,这里是 Todo 这个服务。
我们新建一个文件控制客户端相关逻辑:client/miniprogram/service/todo.ts
创建一个 Todo
export namespace TodoService {
export function CreateTodo(req: todo.v1.ICreateTodoRequest): Promise<todo.v1.ICreateTodoResponse>{
return SDK.sendRequestWithAuthRetry({
method: "POST",
path: "/v1/todo",
data: req,
respMarshaller: todo.v1.CreateTodoResponse.fromObject
})
}
}
低层弄好后,上层堆业务就爽很多了。
Refs
- grpc-ecosystem/go-grpc-middleware
- API Security : API key is dead..Long live Distributed Token by value
- Demo: go-grpc-gateway-v2-microservice
- gRPC-Gateway
- gRPC-Gateway Docs
我是为少
微信:uuhells123
公众号:黑客下午茶
加我微信(互相学习交流),关注公众号(获取更多学习资料~)
Go+gRPC-Gateway(V2) 微服务实战,小程序登录鉴权服务(六):客户端基础库 TS 实战的更多相关文章
- Go+gRPC-Gateway(V2) 微服务实战,小程序登录鉴权服务(五):鉴权 gRPC-Interceptor 拦截器实战
拦截器(gRPC-Interceptor)类似于 Gin 中间件(Middleware),让你在真正调用 RPC 服务前,进行身份认证.参数校验.限流等通用操作. 系列 云原生 API 网关,gRPC ...
- Go+gRPC-Gateway(V2) 微服务实战,小程序登录鉴权服务(四):客户端强类型约束,自动生成 API TS 类型定义
系列 云原生 API 网关,gRPC-Gateway V2 初探 Go + gRPC-Gateway(V2) 构建微服务实战系列,小程序登录鉴权服务:第一篇 Go + gRPC-Gateway(V2) ...
- Go + gRPC-Gateway(V2) 构建微服务实战系列,小程序登录鉴权服务:第一篇(内附开发 demo)
简介 小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系. 系列 云原生 API 网关,gRPC-Gateway V2 初探 业务流程 官方开发接入文档 ...
- 微信小程序登录鉴权流程图
- Flask与微信小程序登录(后端)
开发微信小程序时,接入小程序的授权登录可以快速实现用户注册登录的步骤,是快速建立用户体系的重要一步.这篇文章将介绍 python + flask + 微信小程序实现用户快速注册登录方案(本文主要进行后 ...
- 微慕WordPress小程序增强版
2017年1月9日,张小龙在2017微信公开课Pro上发布的微信小程序正式上线.在过去的2年多的时间里,微信小程序领头,各大互联网平台也不甘落后,陆续推出自己的小程序.2018年7月4日,百度智能小程 ...
- JeeWx捷微3.1小程序版本发布,支持微信公众号,微信企业号,支付窗——JAVA版开源微信管家
支持小程序,JeeWx捷微3.1小程序版本发布^_^ JeeWx捷微V3.1——多触点小程序版本管理平台(支持微信公众号,微信企业号,支付窗) JeeWx捷微V3.1.0版本紧跟微信小程序更新,在 ...
- JAVA版开源微信管家—JeeWx捷微3.1小程序版本发布,支持微信公众号,微信企业号,支付窗
支持小程序,JeeWx捷微3.1小程序版本发布^_^ JeeWx捷微V3.1--多触点小程序版本管理平台(支持微信公众号,微信企业号,支付窗) JeeWx捷微V3.1.0版本紧跟微信小程序更新,在原有 ...
- 小程序server-3-搭建WebSocket 服务
小程序server-3-搭建WebSocket 服务: 1.安装 Node 模块 使用 ws 模块来在服务器上支持 WebSocket 协议,下面使用 NPM 来安装: cd /var/www/wxp ...
随机推荐
- ubuntu ARM换国内源和国内源安装ROS
ubuntu arm换国内源: https://www.cnblogs.com/yongy1030/p/10315569.html 国内源安装ROS: https://blog.csdn.net/ch ...
- 记一个关于std::unordered_map并发访问的BUG
前言 刷题刷得头疼,水篇blog.这个BUG是我大约一个月前,在做15445实现lock_manager的时候遇到的一个很恶劣但很愚蠢的BUG,排查 + 摸鱼大概花了我三天的时间,根本原因是我在使用s ...
- java自学第5期——Object、Date、Calender、System、StringBuilder、基本类型包装类
一.Object类 作用:对象操作 位置:java.lang.Object 方法: public String toString() :返回对象的字符串表示形式. public boolean equ ...
- Redis 内存淘汰机制详解
一般来说,缓存的容量是小于数据总量的,所以,当缓存数据越来越多,Redis 不可避免的会被写满,这时候就涉及到 Redis 的内存淘汰机制了.我们需要选定某种策略将"不重要"的数据 ...
- vmware-install.pl 如何安装?
首先在虚拟机上安装vnware-tools工具,如图(工具为vmware workstation): 成功 但是系统屏幕大小并没有适应虚拟机,所以下边这行提示很重要. 打开左侧边栏的VMware ...
- Kubernetes-7.Ingress
docker version:20.10.2 kubernetes version:1.20.1 本文概述Kubernetes Ingress基本原理和官方维护的Nginx-Ingress的基本安装使 ...
- 面试系列二:精选大数据面试真题JVM专项-附答案详细解析
公众号(五分钟学大数据)已推出大数据面试系列文章-五分钟小面试,此系列文章将会深入研究各大厂笔面试真题,并根据笔面试题扩展相关的知识点,助力大家都能够成功入职大厂! 大数据笔面试系列文章分为两种类型: ...
- 剑指 Offer 41. 数据流中的中位数 + 堆 + 优先队列
剑指 Offer 41. 数据流中的中位数 Offer_41 题目详情 题解分析 本题使用大根堆和小根堆来解决这个寻找中位数和插入中位数的问题. 其实本题最直接的方法是先对数组进行排序,然后取中位数. ...
- Nodejs学习笔记(5) 文件上传系统实例
目录 2018.8.4更新: MySQL可以存放几乎任何类型的数据(图片.文档.压缩包等),但这不是最好的解决方案,正常情况下都是在数据库中存放文件路径,图片.音乐.视频.压缩包.文档等文件存放在硬 ...
- Cookie实现记住密码、自动登录
前端代码 <form id="form" action="xxx" method="post"> <div> < ...