首页 > 编程知识 正文

微信小程序授权登录流程界面,微信小程序登陆授权流程

时间:2023-05-04 13:30:32 阅读:270686 作者:1539

https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html     微信小程序官方API

说明:

调用 wx.login() 获取 临时登录凭证code ,并回传到开发者服务器。调用 code2Session 接口,换取 用户唯一标识 OpenID 和 会话密钥 session_key

之后开发者服务器可以根据用户标识来生成自定义登录态,用于后续业务逻辑中前后端交互时识别用户身份。

注意:

会话密钥 session_key 是对用户数据进行 加密签名 的密钥。为了应用自身的数据安全,开发者服务器不应该把会话密钥下发到小程序,也不应该对外提供这个密钥。临时登录凭证 code 只能使用一次

 

这里仅按照官方推荐的规范来

0. 前置条件

一共有三端: 
- 微信小程序客户端 
- 第三方服务器端
- 微信服务器端

1.检测登录是否有效,如果无效则清楚登录信息(wx.checkSession);


2.调用接口获取登录凭证(code)(wx.login);通过凭证进而换取用户登录态信息,包括用户的唯一标识(openid)及本次登录的会话密钥(session_key)等。用户数据的加解密通讯需要依赖会话密钥完成。

3. 客户端获得code,并将code传给第三方服务端

微信小程序端调用wx.login,获取登录凭证(code),并调用接口,将code发送到第三方客户端

4. 第三方服务端用code换session_key和openid

小程序端将code传给第三方服务器端,第三方服务器端调用接口,用code换取session_key和openid

5. 第三方服务端生成新的session(3rd_session)

第三方服务器端拿到请求回来的session_key和openid,先留着,不能给客户端;然后用操作系统提供的真正随机数算法生成一个新的session,叫3rd_session

6. 第三方服务端建立对应关系,并存储

将3rd_session作为key,微信服务端返回的session_key和openid作为值,保存起来

7. 第三方服务端将3rd_session发送到客户端

客户端只拿到3rd_session就够了,大人说话小孩别插嘴,小程序不需要知道session_key和openid

8. 正常请求

小程序每次请求都将3rd_session放在请求头里,第三方服务端解析判断合法性,并进行正常的逻辑处理。

 

下面就封装一个小程序授权登录的组件

目录结构

1.server.js

//检测登录是否有效,如果无效则清除登录信息module.exports = {checkLogs() {    let utoken = wx.getStorageSync("userInfo").utoken;    if (typeof utoken == "undefined") {      return false;    }    this.sendRequest({      url: '',   //  //检测登录是否有效的接口      data: {        utoken      },      method: 'POST',      success: res => {        if (res.data.code != 200) {          wx.removeStorageSync('userInfo');        }      },      fail: () => {        wx.removeStorageSync('userInfo');      }    })  }, //这里使用了iview框架,全局控制handleShow方法,授权登录的显示login: function() {    const selector = '#login'    const pages = getCurrentPages();    const ctx = pages[pages.length - 1];    const componentCtx = ctx.selectComponent(selector);    if (!componentCtx) {      console.error('无法找到对应的组件,请按文档说明使用组件');      return null;    }    componentCtx.handleShow();  }}

app.js

var server = require('./utils/server');App({  onLaunch: function() {    server.checkLogs();//全局调用checkLogs(),检查登录是否失效  },  globalData: {}})

login.wxml

<!--component/login/login.wxml--><view class='fixBox' catchtouchmove='touchMove' catchtap='handleHide' wx:if="{{visible}}">  <form report-submit="true">    <button type='primary' form-type='submit' open-type="getUserInfo" catchtap='cantchTap' bindgetuserinfo="getUserInfo">一键授权</button>  </form></view> <i-message id="message"/>注意:wx.authorize({scope: "scope.userInfo"}),无法弹出授权窗口,请使用 <button open-type="getUserInfo"/>

login.js

// component/login/login.jsconst server = require('../../utils/server.js');Component({  properties: {  },  data: {    formid: null,    visible: false  },  methods: {    handleShow() {      this.setData({        visible: true      })    },    handleHide() {      this.setData({        visible: false      })    },    touchMove() {      return false;    },    cantchTap() {      return false;    },    getUserInfo(res) {      if (res.detail.errMsg == 'getUserInfo:ok') {        let userInfo = {          ...res.detail.userInfo        }        wx.login({          success: e => {                   let code = e.code;  //调用wx.login,获取登录凭证(code),并调用接口,将code发送到第三方客户端            server.sendRequest({              url: '',       //小程序端将code传给第三方服务器端,第三方服务器端调用接口,用code换取session_key和openid              data: {                encryptedData: res.detail.encryptedData,                iv: res.detail.iv,                code: code              },              method: 'POST',              success: res => {                if (res.data.code == 200) {                  userInfo = {                    ...userInfo,                    ...res.data.result                  }                  console.log(userInfo);                  console.log(res.data.result)                  wx.setStorageSync('userInfo', userInfo);                  //授权成功                  this.triggerEvent('login', {                    status: 1                  })                  this.$Message({                    content: '登录成功',                    type: "success"                  })                  this.handleHide();                } else {                  this.triggerEvent('login', {                    status: 0                  })                  this.$Message({                    content: '登录失败',                    type: 'error'                  });                  this.handleHide();                }              }            })          }        })      } else {        this.triggerEvent('login', {          status: 0        })        this.$Message({          content: '登录失败',          type: 'error'        });        this.handleHide();      }    },    $Message(options) {  //把iview框架里的方法抽取出来      const componentCtx = this.selectComponent("#message");      componentCtx.handleShow(options);    }  }})

login.json

​{  "component": true,  "usingComponents": {    "i-message": "/component/iview/message/index"  //引用iview框架里全局提示框  }}​

login.wxss

index.wxml

<view class='head'>  <block wx:if="{{userInfo}}">    <image class="avatarImg" src="{{userInfo.avatarUrl}}"></image>    <view class="nickname">{{userInfo.nickName}}</view>  </block>  <block wx:else>    <image class="avatarImg" bindtap="login" src="/images/avatar.png"></image>    <view class="nickname" bindtap="login">未登录</view>  </block></view><view class="order">  <view class="list orderTitle">    <view class="listTitle">我的订单</view>    <view class="readMore" bindtap='seeMore'>      <text>查看更多</text>      <image class="toRight" src="/images/toRight.png"></image>    </view>  </view></view><login id="login" bind:login="onLogin"></login>

index.js

const server = require('../../utils/server.js');Page({  data: {    useInfo: null  },  onLoad: function(options) {},  onShow: function() {  },  onLogin(res) {  // 授权成功的回调,根据子组件传过来的status    if (res.detail.status == 1) {      let userInfo = wx.getStorageSync('userInfo');      this.setData({        userInfo      })    }  },  navigateTo(option) {  // 封装一个具有判断是否授权登录的跳转方法    if (wx.getStorageSync("userInfo")) {      wx.navigateTo(option);    } else {      server.login();    }  },  seeMore() {    this.navigateTo({      url: '/pages/order/orderList/orderList'    })  },})

index.wxss

page {  background-color: #eee;}.head {  width: 100%;  height: 250rpx;  background-color: #fff;  box-sizing: border-box;  padding: 0 20rpx;  border-top: 1rpx solid #eee;  display: flex;  align-items: center;  justify-content: flex-start;}.avatarImg {  width: 150rpx;  height: 150rpx;  border-radius: 50%;}.nickname {  display: inline-block;  font-size: 40rpx;  font-weight: 600;  color: #212121;  margin-left: 20rpx;}.order, .tool {  margin-top: 20rpx;  background-color: #fff;}.list {  border-bottom: 2rpx solid #eee;  height: 100rpx;  box-sizing: border-box;  padding: 0 20rpx;}.orderTitle {  display: flex;  align-items: center;  justify-content: space-between;}.listTitle {  color: #232323;  font-size: 35rpx;}.readMore {  line-height: 100rpx;  font-size: 30rpx;  color: #989898;  display: flex;  align-items: center;}.toRight {  width: 28rpx;  height: 28rpx;  margin-left: 20rpx;}

index.json

{    "usingComponents": {        "login": "/component/login/login",        "i-message": "/component/iview/message/index"    }}

解释都在代码里面
 

 

 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。