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

说明:
- 调用 wx.login() 获取 临时登录凭证code ,并回传到开发者服务器。
- 调用 code2Session 接口,换取 用户唯一标识 OpenID 和 会话密钥 session_key。
之后开发者服务器可以根据用户标识来生成自定义登录态,用于后续业务逻辑中前后端交互时识别用户身份。
注意:
- 会话密钥
session_key是对用户数据进行 加密签名 的密钥。为了应用自身的数据安全,开发者服务器不应该把会话密钥下发到小程序,也不应该对外提供这个密钥。 - 临时登录凭证 code 只能使用一次
这里仅按照官方推荐的规范来
0. 前置条件
1.检测登录是否有效,如果无效则清楚登录信息(wx.checkSession);
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
注意:wx.authorize({scope: "scope.userInfo"}),无法弹出授权窗口,请使用
login.js
// component/login/login.js const 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
{
{userInfo.nickName}}
未登录
我的订单
查看更多
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: #; 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: #; font-size: 35rpx; } .readMore { line-height: 100rpx; font-size: 30rpx; color: #; 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" } }
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/208411.html原文链接:https://javaforall.net
