通过扫小程序码实现网站登陆功能


Posted in Javascript onAugust 22, 2019

网络上关于实现本本功能的文章很多,但是给出案列的几乎没有,今天笔者实现用小程序码实现网站登陆,体验地址如下

https://idea.techidea8.com/open/login.shtml

思路

通过扫小程序码实现网站登陆功能

核心流程

关键流程

建立场景sceneid和websocket的绑定关系

获得sceneid

场景ID可以前端生成,也可以后端生成,只需要保证sceneid的同一时间唯一性即可。

前端生成可以采用随机数加时间戳的形式,也可以用uuid算法

//时间戳
var sceneid ="scend-" + new Data().getTime() + Math.ceil(Math.random()*888888+1000000);
建立websocket
var ws = new WebSocket("ws://192.168.0.106/websocket?clientid="+sceneid )
ws.onopen=function(env){
 console.log(env)
} 
ws.onmessage=function(env){
 var data = env.data;
 //这个data 就是后端发来的用户数据
}

后端建立websocket

后端采用go语言github.com/gorilla/websocket包建立websocket.因为golang 非常适合高并发场景。

func (ctrl *PushCtrl) websocket(w http.ResponseWriter, req *http.Request) {
 //fmt.Printf("%+v",request.Header)
 //todo 检验接入是否合法
 //checkToken(userId int64,token string)
 query := req.URL.Query()
 clientid := query.Get("clientid")
 conn, err := (&websocket.Upgrader{
  CheckOrigin: func(r *http.Request) bool {
   return true
  },
 }).Upgrade(w, req, nil)
 if err != nil {
  log.Println(err.Error())
  return
 }
 clientMap.Store(clientid, conn)
 go func(clientId string, conn *websocket.Conn) {
  //处理出错信息
  defer func() {
   conn.Close()
   clientMap.Delete(clientid)
  }()
  for {
   _, _, err := conn.ReadMessage()
   if err != nil {
    log.Println(err.Error())
    return
   }
  }
 }(clientid, conn)
}

我们采用sync.map建立sceneid和websocket的对应关系

clientMap.Save(sceneid,conn)

对于因为异常断开的con我们需要移除

clientMap.Delete(sceneid)

获得小程序二维码

获得小程序的accesstoken

小程序access 请求接口如下
``

该接口日使用频率有限制,因此我们需要将这些数据缓存起来,缓存方案很多,有redis,也有内存,我们这里直接用一个变量即可存储

accesstoken :=""
func GetAccessToken() string{
 return accesstoken 
}
func RefreshAccessToken()string{
 url = ""
 resp := httpget(url)
 //resp 是一个包含accesstoken的json字符串,我们解析这个json即可
 accesstoken = decodeaccesstokenfromjson(resp)
 return accesstoken 
}

我们还需要一个滴答计数器用来刷新accesstoken,accesstoken 的有效期是7200秒,我们4000秒刷新一次accesstoken 即可

func refreshAccessToken(){
 ticker := time.NewTicker(time.Second *4000)
 for{
  select {
   case <-ticker.C:
    RefreshAccessToken()
  }
 }
}

在init.go 中的init方法中启动协程

go refreshAccessToken()

小程序二维码编程技巧

小程序二维码请求接口如下

https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESSTOKEN

由于该链接会返回俩种结果

错误返回Json

{
"errcode":400001,
"errmsg":"什么什么原因"
}

正确返回j图片buffer

这是一个二进制码流,因此我们需要对返回结果进行标准化处理

我们建议一种标准化结果

{
code:0,
data:"",
msg:"结果说明"
}

参数 说明
code 标识成功或者失败,200为成功,400为失败
data 图片的base64格式编码
msg 结果说明,或者出错提示

代码示例如下

url := fmt.Sprintf("https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%s", token)
ret, err := util.PostJSON(url, arg)
if err != nil {
    util.FailMsg(w, err.Error())
    return
}

jsonstr := string(ret)
if strings.Contains(jsonstr, "errmsg") {
  util.FailMsg(w, jsonstr)
  return
} else {
  base64data := base64.StdEncoding.EncodeToString(ret)
  util.RespOk(w, "data:image/png;base64,"+base64data)
}

其中util是笔者封装的常用工具包

通过扫小程序码实现网站登陆功能

常用工具包

前端请求成功后获得data,可以利用$("#qrcode").attr("src",res.data)刷新图片二维码

function refreshqrcode(){
  clientId = "scene-"+new Date().getTime();
  var api = restgo.buildapi("miniapp/getwxacodeunlimit")
  restgo.post(api,{"scene":clientId}).then(res=>{
    if(res.code==200){
      $("#qrcode").attr("src",res.data)
    }else{
      alert(res.msg)  
    }
    intiwebsocket()
  },res=>{
    alert(res.msg)
  })
}

小程序处理关键点

采用好的框架

我们编程过程才用了uniapp,这个框架不错,完全是vue的语法,

一套代码可以生成H5/小程序/android/ios

我们采用了vue的watch特性,通过监听userid来确定是否发送信息

watch:{
   userid:function(a,b){
      
      if(a==0){
        return 
      }
      
      this.loaddata()
      //如果clientid是空的说明不是扫码进来的  
      if(!this.clientid){
        return 
      }
//如果是扫码进来的,那么我们还需要推送消息到服务器后端
server.PublishMsg(this.clientid,this.userid,this.role,this.avatarUrl,this.nickName).then(res=>{
        tip.error(res.msg)
      },res=>{
        tip.error(res.msg)
      })
      
   }
 }

获取sceneid

我们通过onload方法获得sceneid

onLoad(arg) {
    if(!!arg && !!arg.scene){
          this.clientid = decodeURIComponent(arg.scene)
    }
        
  },

核心代码如下

通过gotUserInfo获得用户头像、昵称等,通过uni.login获得code

gotUserInfo :function(e) {
       //获得用户头像、昵称、
       uni.login(
       {
         success:(res) =>{
              //通过wx.login获得code
              userInfo.code = res.code
                        //统一传递到后端   
            this.authwithcode(userInfo)
         }
       }
       )
      }
     },
    authwithcode:function(userInfo){
            //code获得openid在后端做,做了后继续去查User表
      server.AuthWithCode(userInfo).then(res=>{
          //如果这个openid绑定了用户                                  
          if(res.data.id>0){
            //这里res.data 就是user对象,可以继续操作
            return ;
          }
          //如果没有那么注册
          server.RegisterWithOpenId(res.data.mini_openid,userInfo.avatarUrl,userInfo.nickName)#.then(res=>{
            //注册成功则返回
            //这里res.data 就是user对象可以继续操作
            
          },res=>{
            tip.error(res.msg)
          })
        },res=>{
          tip.error(res.msg||"");
        })
      }
    },

体验地址

本文所有应用体验地址如下

互联网行业解决方案吧https://idea.techidea8.com/open/idea.shtml?id=5

关于代码

代码获得地址

小程序码登陆

总结

以上所述是小编给大家介绍的通过扫小程序码实现网站登陆功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
JavaScript实现为指定对象添加多个事件处理程序的方法
Apr 17 Javascript
JavaScript中字符串(string)转json的2种方法
Jun 25 Javascript
Javascript实现倒计时(防页面刷新)实例
Dec 13 Javascript
js调用刷新界面的几种方式
May 03 Javascript
提高Node.js性能的应用技巧分享
Aug 10 Javascript
搭建vue开发环境
Jul 19 Javascript
浅谈HTTP 缓存的那些事儿
Oct 17 Javascript
javascript中如何判断类型汇总
May 14 Javascript
axios如何利用promise无痛刷新token的实现方法
Aug 27 Javascript
element-ui 远程搜索组件el-select在项目中组件化的实现代码
Dec 04 Javascript
详解小程序BackgroundAudioManager踩坑之旅
Dec 08 Javascript
在vue项目中 实现定义全局变量 全局函数操作
Oct 26 Javascript
vue中实现上传文件给后台实例详解
Aug 22 #Javascript
js的新生代垃圾回收知识点总结
Aug 22 #Javascript
JS实现移动端在线签协议功能
Aug 22 #Javascript
jQuery表单选择器用法详解
Aug 22 #jQuery
node实现简单的增删改查接口实例代码
Aug 22 #Javascript
微信小程序实现上传图片裁剪图片过程解析
Aug 22 #Javascript
ES6基础之 Promise 对象用法实例详解
Aug 22 #Javascript
You might like
Php中用PDO查询Mysql来避免SQL注入风险的方法
2013/04/25 PHP
修改destoon会员公司的伪静态中的com目录的方法
2014/08/21 PHP
yii添删改查实例
2015/11/16 PHP
php实现批量上传数据到数据库(.csv格式)的案例
2017/06/18 PHP
javascript setTimeout和setInterval 的区别
2009/12/08 Javascript
javascript 定义新对象方法
2010/02/20 Javascript
最常用的12种设计模式小结
2011/08/09 Javascript
javaScript复制功能调用实现方案
2012/12/13 Javascript
jQuery实现统计输入文字个数的方法
2015/03/11 Javascript
JS中Location使用详解
2015/05/12 Javascript
JavaScript ParseFloat()方法
2015/12/18 Javascript
jQuery 3.0十大新特性最终版发布
2016/07/14 Javascript
详解AngularJs HTTP响应拦截器实现登陆、权限校验
2017/04/11 Javascript
详解webpack 多入口配置
2017/06/16 Javascript
bootstrap select下拉搜索插件使用方法详解
2017/11/23 Javascript
jQuery+SpringMVC中的复选框选择与传值实例
2018/01/08 jQuery
vue.js使用代理和使用Nginx来解决跨域的问题
2018/02/03 Javascript
详解vue中localStorage的使用方法
2018/11/22 Javascript
详解vue-cli3多环境打包配置
2019/03/28 Javascript
vue + typescript + video.js实现 流媒体播放 视频监控功能
2019/07/07 Javascript
解决Vue.js应用回退或刷新界面时提示用户保存修改问题
2019/11/24 Javascript
原生js+ajax分页组件
2020/01/30 Javascript
jQuery实现查看图片功能
2020/12/01 jQuery
详解Python数据分析--Pandas知识点
2019/03/23 Python
python pip源配置,pip配置文件存放位置的方法
2019/07/12 Python
Django实现文件上传下载
2019/10/06 Python
python ctypes库2_指定参数类型和返回类型详解
2019/11/19 Python
解析pip安装第三方库但PyCharm中却无法识别的问题及PyCharm安装第三方库的方法教程
2020/03/10 Python
Django choices下拉列表绑定实例
2020/03/13 Python
Russell Stover巧克力官方网站:美国领先的精美巧克力制造商
2016/11/27 全球购物
物业管理大学生个人的自我评价
2013/10/10 职场文书
升旗仪式演讲稿
2014/05/08 职场文书
高中生第一学年自我鉴定
2014/09/12 职场文书
《彼得与狼》教学反思
2016/02/20 职场文书
基于Python实现射击小游戏的制作
2022/04/06 Python
MySQL数据库如何使用Shell进行连接
2022/04/12 MySQL