golang后端接入MOB的短信服务

2023-11-27 03:00

本文主要是介绍golang后端接入MOB的短信服务,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

背景:

初学golang,想和同学前后端分离做个小APP,我负责后端。
需要用到短信服务来做验证码登陆,选择了MobTech的SMS服务(一个月免费1W条,MOB牛逼!)

问题:

以前做的短信登陆逻辑如图:
在这里插入图片描述
MOB文档中给出了两种策略:
在这里插入图片描述
在这里插入图片描述
我感觉第一种后端不涉及验证过程的策略可能存在安全隐患,因为校验短信验证码的动作发生在前端,之后由开发者在前端回调后台的业务接口诸如登陆和注册。
那么在调用这一业务接口时,肯定需要前端引入某种加密策略,来确保对该接口的请求一定是前端经过完整的验证码流程后发起的,只有这样才能保证用户身份的正确。
在这种情况下,如果前端的加密策略泄露,可能导致不法分子伪装其他用户的身份进行登陆或其他权限相关操作,就糟糕了。

以上仅是我这个初学者结合以往经验的一点点猜测,既然这种模式存在于官方文档中,那肯定有足够安全的实现策略,不过我现在还不知道: (

我暂时就先用自己理解上觉得更安全、更顺手的第二种策略来实现。

在此先附上MobTech的SMS服务接入文档:
Mob文档中心 / SMSSDK

注册账号并创建应用、企业认证过程这里就不提了。
前端根据不同实现可以参考上述文档快速接入SDK。
后端如果要采用第二种策略,需要进行以下操作:

  1. 填入部署后端应用的服务器的ip
    在这里插入图片描述
  2. 对Mob提供的验证码校验接口进行封装
package smsimport ("encoding/json""errors""fmt""io/ioutil""net/http""net/url""strings"
)//短信服务功能封装//默认区号为中国(+86)
const DEFAULT_ZONE = "86"//MOB提供的验证码校验接口
const VERIFY_URL = "https://webapi.sms.mob.com/sms/verify"const APP_KEY = "xxxxxxxx"
const APP_SECRET = "xxxxxxxxxxxxxxxxxxxxxxxxxx"//校验收到的验证码
func VerifyCode(phone, code string) (bool, error) {//********************************************************//* 通过json的方式进行post请求的传参  在这里是不适用的!!!    *//********************************************************//contentType := "application/json"//data := mapToJSON(&map[string]interface{}{//	"phone":  phone,//	"code":   code,//	"appkey": "31db8a6381fb0",//	"zone":   DEFAULT_ZONE,//})//resp, err := http.Post(VERIFY_URL, contentType, strings.NewReader(data))urlValues := url.Values{"phone":  {phone},"code":   {code},"appkey": {APP_KEY},"zone":   {DEFAULT_ZONE},}reqBody:= urlValues.Encode()resp, err := http.Post(VERIFY_URL, "text/html",strings.NewReader(reqBody))if err != nil {fmt.Printf("post failed, err:%v\n", err)return false, err}defer resp.Body.Close()b, err := ioutil.ReadAll(resp.Body)if err != nil {fmt.Printf("get resp failed, err:%v\n", err)return false, err}//json序列化成map 解析MOB验证接口的返回值var tempMap map[string]interface{}err = json.Unmarshal([]byte(b), &tempMap)if err != nil {fmt.Printf("parse resp failed, err:%v\n", err)return false, err}fmt.Println("接口返回的状态码是:",tempMap["status"])fmt.Println("接口返回的message是:",tempMap["error"])//根据接口返回状态码 判断验证码结果switch int(tempMap["status"].(float64)) {case 200:return true, nildefault:return false,errors.New(tempMap["error"].(string))}
}//map转json
func mapToJSON(tempMap *map[string]interface{}) string {data, err := json.Marshal(tempMap)if err != nil {panic(err)}return string(data)
}

注意,这里有一个坑!
在golang里,post请求传参有三种常见的方式:

  • conten-type : text/html 这种实际上是把参数拼接到url上)

  • conten-type : application/x-www-form-urlencoded

  • conten-type : application/json

    对应到golang代码中有以下三种写法:

  •  	  urlValues := url.Values{"name":{"zhaofan"},"age":{"23"},}reqBody:= urlValues.Encode()resp, _ := http.Post("http://xxxxxx", "text/html",strings.NewReader(reqBody))body,_:= ioutil.ReadAll(resp.Body)fmt.Println(string(body))
    
  •      urlValues := url.Values{}urlValues.Add("name","zhaofan")urlValues.Add("age","22")resp, _ := http.PostForm("http://httpbin.org/post",urlValues)body, _ := ioutil.ReadAll(resp.Body)fmt.Println(string(body))
    
  •  	 data := mapToJSON(&map[string]interface{}{"phone":  phone,"code":   code,"appkey": "31db8a6381fb0","zone":   DEFAULT_ZONE,})resp, _:= http.Post(VERIFY_URL, contentType, strings.NewReader(data))body, _ := ioutil.ReadAll(resp.Body)fmt.Println(string(body))//map转jsonfunc mapToJSON(tempMap *map[string]interface{}) string {data, err := json.Marshal(tempMap)if err != nil {panic(err)}return string(data)}
    

当我使用第三种JSON传参的时候,MOB的验证接口一直给我报405 AppKey为空
改用第一种、第二种传参方式之后都能够正常调用。
估计是mob提供的这个接口在解析参数时不支持json传参。

这也体现出了gin框架在http请求参数解析时的强大之处:
只需要在声明接收参数的结构体时,给对应字段添加几个“注解”
(暂时不知道这个小引号的学名,先这么叫它^^)
再结合func (c *Context) ShouldBind(obj interface{}) error就能完美实现httpRequest的参数获取。

//接受参数的实体
type Verify struct {Phone    string     `form:"phone" json:"phone" binding:"required"`Code     string 	`form:"code" json:"code" binding:"required"`
}var verify Verify	//用于装载参数的结构体
if err := c.ShouldBind(&verify); err == nil {...}//读取参数后的业务逻辑
  1. 给前端提供校验接口,可以整合自己的登陆或注册等等业务逻辑
//接受参数的实体
type Verify struct {Phone    string `form:"phone" json:"phone" binding:"required"`Code string 	`form:"code" json:"code" binding:"required"`
}
//这是一个功能接口 POST类型 路由为 '/phone' 用于手机或者注册
func phone(c *gin.Context) {//获取请求参数...业务逻辑var verify Verifyif err := c.ShouldBind(&verify); err == nil {fmt.Printf("verify info:%#v\n", verify)//1、校验验证码isCorrect,_ := sms.VerifyCode(verify.Phone,verify.Code)//验证码正确if isCorrect {//2、校验手机号是否存在 不存在则先注册再返回token 存在则直接返回tokenbyPhone, _ := service.GetUserByPhone(verify.Phone)if byPhone==(bean.User{}) {//用户不存在c.JSON(http.StatusOK,response.Ok("新用户注册成功",nil))}else{//用户已存在c.JSON(http.StatusOK,response.Ok("登陆成功",nil))}}else{//验证码不正确c.JSON(http.StatusOK,response.Fail("验证码错误"))}} else {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})}
}



收工!

在这里插入图片描述

这篇关于golang后端接入MOB的短信服务的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/426906

相关文章

【区块链 + 人才服务】可信教育区块链治理系统 | FISCO BCOS应用案例

伴随着区块链技术的不断完善,其在教育信息化中的应用也在持续发展。利用区块链数据共识、不可篡改的特性, 将与教育相关的数据要素在区块链上进行存证确权,在确保数据可信的前提下,促进教育的公平、透明、开放,为教育教学质量提升赋能,实现教育数据的安全共享、高等教育体系的智慧治理。 可信教育区块链治理系统的顶层治理架构由教育部、高校、企业、学生等多方角色共同参与建设、维护,支撑教育资源共享、教学质量评估、

【区块链 + 人才服务】区块链集成开发平台 | FISCO BCOS应用案例

随着区块链技术的快速发展,越来越多的企业开始将其应用于实际业务中。然而,区块链技术的专业性使得其集成开发成为一项挑战。针对此,广东中创智慧科技有限公司基于国产开源联盟链 FISCO BCOS 推出了区块链集成开发平台。该平台基于区块链技术,提供一套全面的区块链开发工具和开发环境,支持开发者快速开发和部署区块链应用。此外,该平台还可以提供一套全面的区块链开发教程和文档,帮助开发者快速上手区块链开发。

基于SpringBoot的宠物服务系统+uniapp小程序+LW参考示例

系列文章目录 1.基于SSM的洗衣房管理系统+原生微信小程序+LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统+LW参考示例 3.基于SpringBoot+Vue的企业人事管理系统+LW参考示例 4.基于SSM的高校实验室管理系统+LW参考示例 5.基于SpringBoot的二手数码回收系统+原生微信小程序+LW参考示例 6.基于SSM的民宿预订管理系统+LW参考示例 7.基于

Golang进程权限调度包runtime

关于 runtime 包几个方法: Gosched:让当前线程让出 cpu 以让其它线程运行,它不会挂起当前线程,因此当前线程未来会继续执行GOMAXPROCS:设置最大的可同时使用的 CPU 核数Goexit:退出当前 goroutine(但是defer语句会照常执行)NumGoroutine:返回正在执行和排队的任务总数GOOS:目标操作系统NumCPU:返回当前系统的 CPU 核数量 p

Golang 网络爬虫框架gocolly/colly(五)

gcocolly+goquery可以非常好地抓取HTML页面中的数据,但碰到页面是由Javascript动态生成时,用goquery就显得捉襟见肘了。解决方法有很多种: 一,最笨拙但有效的方法是字符串处理,go语言string底层对应字节数组,复制任何长度的字符串的开销都很低廉,搜索性能比较高; 二,利用正则表达式,要提取的数据往往有明显的特征,所以正则表达式写起来比较简单,不必非常严谨; 三,使

Golang网络爬虫框架gocolly/colly(四)

爬虫靠演技,表演得越像浏览器,抓取数据越容易,这是我多年爬虫经验的感悟。回顾下个人的爬虫经历,共分三个阶段:第一阶段,09年左右开始接触爬虫,那时由于项目需要,要访问各大国际社交网站,Facebook,myspace,filcker,youtube等等,国际上叫得上名字的社交网站都爬过,大部分网站提供restful api,有些功能没有api,就只能用http抓包工具分析协议,自己爬;国内的优酷、

Golang网络爬虫框架gocolly/colly(三)

熟悉了《Golang 网络爬虫框架gocolly/colly 一》和《Golang 网络爬虫框架gocolly/colly 二》之后就可以在网络上爬取大部分数据了。本文接下来将爬取中证指数有限公司提供的行业市盈率。(http://www.csindex.com.cn/zh-CN/downloads/industry-price-earnings-ratio) 定义数据结构体: type Zhj

Golang支持平滑升级的HTTP服务

前段时间用Golang在做一个HTTP的接口,因编译型语言的特性,修改了代码需要重新编译可执行文件,关闭正在运行的老程序,并启动新程序。对于访问量较大的面向用户的产品,关闭、重启的过程中势必会出现无法访问的情况,从而影响用户体验。 使用Golang的系统包开发HTTP服务,是无法支持平滑升级(优雅重启)的,本文将探讨如何解决该问题。 一、平滑升级(优雅重启)的一般思路 一般情况下,要实现平滑

Golang服务平滑重启

与重载配置相同的是我们也需要通过信号来通知server重启,但关键在于平滑重启,如果只是简单的重启,只需要kill掉,然后再拉起即可。平滑重启意味着server升级的时候可以不用停止业务。 我们先来看下Github上有没有相应的库解决这个问题,然后找到了如下三个库: facebookgo/grace - Graceful restart & zero downtime deploy for G

Golang test编译使用

创建文件my_test.go package testsimport "testing"func TestMy(t *testing.T) {t.Log("TestMy")} 通常用法: $ go test -v -run TestMy my_test.go=== RUN TestMyTestMy: my_test.go:6: TestMy--- PASS: TestMy (0.