【微信小程序】授权登录流程解析

2025-12-13 0 225

微信授权登录流程

1.官方图示流程详解

【微信小程序】授权登录流程解析

① 微信服务器验证:用户打开小程序时,小程序会向用户展示登录按钮,用户点击登录按钮后,小程序会向微信服务器发送登录请求(wx.login())。微信服务器接收到登录请求后,会验证小程序的身份和合法性。如果小程序通过验证,微信服务器会生成一个临时的登录凭证code)。

code有效时间仅为5分钟,如果5分钟内小程序的后台不拿着这个临时身份证来微信后台服务器换取微信用户id的话,那么这个身份证就会被作废,需要再调用wx.login重新生成登录凭证。

发送code到开发者服务器:在wx.login的success回调中拿到微信登录凭证,紧接着会通过wx.request把code传到开发者服务器,为了后续可以换取微信用户身份id。

如果当前微信用户还没有绑定当前小程序业务的用户身份,那在这次请求应该顺便把用户输入的帐号密码[7]一起传到后台,然后开发者服务器就可以校验账号密码之后再和微信用户id进行绑定

获取用户信息:小程序通过调用微信提供的API,使用临时登录凭证(code)向微信服务器发送请求,以获取用户的唯一标识(openid)和会话密钥(session_key)。

到微信服务器的请求要同时带上AppIdAppSecret ,AppId和AppSecret是微信鉴别开发者身份的重要信息,AppId是公开信息,泄露AppId不会带来安全风险,但是AppSecret是开发者的隐私数据不应该泄露,如果发现泄露需要到小程序管理平台进行重置AppSecret,而code在成功换取一次信息之后也会立即失效,即便凭证code生成时间还没过期。

④绑定微信用户身份id和业务用户身份:此时开发者后台通过校验用户名密码就拿到了业务侧的用户身份id,通过code到微信服务器获取微信侧的用户身份openid。微信会建议开发者把这两个信息的对应关系存起来,我们把这个对应关系称之为“绑定”。

有了这个绑定信息,小程序在下次需要用户登录的时候就可以不需要输入账号密码,因为通过wx.login()获取到code之后,可以拿到用户的微信身份openid,通过绑定信息就可以查出业务侧的用户身份id,这样静默授权的登录方式显得非常便捷。

⑤⑥⑦ 业务登录凭证SessionId:用户登录成功之后,开发者服务器需要生成会话密钥SessionId,在服务端保持SessionId对应的用户身份信息,同时把SessionId返回给小程序。小程序后续发起的请求中携带上SessionId,开发者服务器就可以通过服务器端的Session信息查询到当前登录用户的身份,这样我们就不需要每次都重新获取code,省去了很多通信消耗。

2. 代码登录流程拆解

2.1 前端代码示例讲解

login.js文件:


	【微信小程序】授权登录流程解析 // pages/auth/login/login.js
var util = require(\'../../../utils/util.js\');
var user = require(\'../../../utils/user.js\');
const app = getApp();
Page({

  /**
  * 页面的初始数据
  */
  data: {
    canIUseGetUserProfile: false, // 用于向前兼容
    lock:false
  },
  onLoad: function(options) {
    // 页面初始化 options为页面跳转所带来的参数
    // 页面渲染完成
    if (wx.getUserProfile) {
     this.setData({
      canIUseGetUserProfile: true
     })
    }
    //console.log(\'login.onLoad.canIUseGetUserProfile=\'+this.data.canIUseGetUserProfile)
  },

  /**
  * 生命周期函数--监听页面初次渲染完成
  */
  onReady() {

  },

  /**
  * 生命周期函数--监听页面显示
  */
  onShow() {

  },
  getUserProfile(e) {
    // 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认
    // 开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
    wx.getUserProfile({
      desc: \'用于完善会员资料\', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
      success: (res) => {
        //console.log(res);
        debugger
        user.checkLogin().catch(() => {
          user.loginByWeixin(res.userInfo).then(res => {
           app.globalData.hasLogin = true;
           debugger
           wx.navigateBack({
            delta: 1
           })
          }).catch((err) => {
           app.globalData.hasLogin = false;
           if(err.errMsg==\"request:fail timeout\"){
            util.showErrorToast(\'微信登录超时\');
           }else{
            util.showErrorToast(\'微信登录失败\');
           }
           this.setData({
            lock:false
           })
          });
         });
      },
      fail: (res) => {
        app.globalData.hasLogin = false;
        console.log(res);
        util.showErrorToast(\'微信登录失败\');
      }
    });
  },
  wxLogin: function(e) {
    if (e.detail.userInfo == undefined) {
     app.globalData.hasLogin = false;
     util.showErrorToast(\'微信登录失败\');
     return;
    }
    user.checkLogin().catch(() => {
      user.loginByWeixin(e.detail.userInfo).then(res => {
       app.globalData.hasLogin = true;
       wx.navigateBack({
        delta: 1
       })
      }).catch((err) => {
       app.globalData.hasLogin = false;
       if(err.errMsg==\"request:fail timeout\"){
        util.showErrorToast(\'微信登录超时\');
       }else{
        util.showErrorToast(\'微信登录失败\');
       }
      });
  
     });
  },
  accountLogin() {
    console.log(\'开发中....\')
  }
})

这段代码的作用是实现微信小程序的登录功能。当用户点击登录按钮时,会触发getUserProfile或wxLogin方法,通过获取用户信息并调用登录接口,实现用户的登录操作。登录成功后,会将登录状态保存在全局变量中,并返回上一页。

utils文件夹(封装了登录等方法的工具类) –> user.js文件:


	【微信小程序】授权登录流程解析 /**
* 用户相关服务
*/
const util = require(\'../utils/util.js\');
const api = require(\'../config/api.js\');

/**
* Promise封装wx.checkSession
*/
function checkSession() {
 return new Promise(function(resolve, reject) {
  wx.checkSession({
   success: function() {
    resolve(true);
   },
   fail: function() {
    reject(false);
   }
  })
 });
}
/**
* Promise封装wx.login
*/
function login() {
 return new Promise(function(resolve, reject) {
  wx.login({
   success: function(res) {
    if (res.code) {
     resolve(res);
    } else {
     reject(res);
    }
   },
   fail: function(err) {
    reject(err);
   }
  });
 });
}
/**
* 调用微信登录
*/
function loginByWeixin(userInfo) {
 return new Promise(function(resolve, reject) {
  return login().then((res) => {
   //登录远程服务器
   util.request(api.AuthLoginByWeixin, {
    code: res.code,
    userInfo: userInfo
   }, \'POST\').then(res => {
    if (res.errno === 0) {
     //存储用户信息
     wx.setStorageSync(\'userInfo\', res.data.userInfo);
     wx.setStorageSync(\'token\', res.data.token);
     resolve(res);
    } else {
     reject(res);
    }
   }).catch((err) => {
    reject(err);
   });
  }).catch((err) => {
   reject(err);
  })
 });
}
/**
* 判断用户是否登录
*/
function checkLogin() {
 return new Promise(function(resolve, reject) {
  if (wx.getStorageSync(\'userInfo\') && wx.getStorageSync(\'token\')) {
   checkSession().then(() => {
    resolve(true);
   }).catch(() => {
    reject(false);
   });
  } else {
   reject(false);
  }
 });
}

module.exports = {
 loginByWeixin,
 checkLogin,
};

  1. loginByWeixin(userInfo):这个函数用于进行微信登录操作。它首先调用login()函数获取微信登录凭证(code),然后将凭证和用户信息一起发送给服务器进行登录验证。如果登录成功,将用户信息和令牌(token)存储在本地缓存中,并通过resolve返回成功的结果。如果登录失败,将通过reject返回失败的结果。

  2. checkLogin():这个函数用于判断用户是否已经登录。它首先检查本地缓存中是否存在用户信息和令牌,如果存在,则调用checkSession()函数检查用户的登录状态。如果登录状态有效,通过resolve返回登录状态为true,表示用户已登录。如果登录状态无效或本地缓存中不存在用户信息和令牌,通过reject返回登录状态为false,表示用户未登录。

通过这两个函数,user模块提供了登录和登录状态检查的功能,可以在其他地方调用这些函数来实现用户登录和登录状态的管理。

2.2 后端代码示例讲解

package com.ycxw.ssm.wxcontroller;

/**
* @Autho 云村小威
* @Since 2023/10/22
*/

import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import com.alibaba.fastjson.JSONObject;
import com.ycxw.ssm.annotation.LoginUser;
import com.ycxw.ssm.model.UserInfo;
import com.ycxw.ssm.model.WxLoginInfo;
import com.ycxw.ssm.model.WxUser;
import com.ycxw.ssm.service.UserToken;
import com.ycxw.ssm.service.UserTokenManager;
import com.ycxw.ssm.service.WxUserService;
import com.ycxw.ssm.util.JacksonUtil;
import com.ycxw.ssm.util.ResponseUtil;
import com.ycxw.ssm.util.UserTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import javax.servlet.http.HttpServletRequest;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
* 鉴权服务
*/
@Slf4j
@RestController
@RequestMapping(\”/wx/auth\”)
public class WxAuthController {
@Autowired
private WxMaService wxService;
@Autowired
private WxUserService userService;
/**
* 微信登录
*
* @param wxLoginInfo
* 请求内容,{ code: xxx, userInfo: xxx }
* @param request
* 请求对象
* @return 登录结果
*/
@PostMapping(\”login_by_weixin\”)
public Object loginByWeixin(@RequestBody WxLoginInfo wxLoginInfo, HttpServletRequest request) {

//客户端需携带code与userInfo信息
String code = wxLoginInfo.getCode();
UserInfo userInfo = wxLoginInfo.getUserInfo();
if (code == null || userInfo == null) {
return ResponseUtil.badArgument();
}
//调用微信sdk获取openId及sessionKey
String sessionKey = null;
String openId = null;
try {
long beginTime = System.currentTimeMillis();
//
WxMaJscode2SessionResult result = this.wxService.getUserService().getSessionInfo(code);
// Thread.sleep(6000);
long endTime = System.currentTimeMillis();
log.info(\”响应时间:{}\”,(endTime-beginTime));
sessionKey = result.getSessionKey();//session id
openId = result.getOpenid();//用户唯一标识 OpenID
} catch (Exception e) {
e.printStackTrace();
}

if (sessionKey == null || openId == null) {
log.error(\”微信登录,调用官方接口失败:{}\”, code);
return ResponseUtil.fail();
}else{
log.info(\”openId={},sessionKey={}\”,openId,sessionKey);
}
//根据openId查询wx_user表
//如果不存在,初始化wx_user,并保存到数据库中
//如果存在,更新最后登录时间
WxUser user = userService.queryByOid(openId);

if (user == null) {
user = new WxUser();
user.setUsername(openId);
user.setPassword(openId);
user.setWeixinOpenid(openId);
user.setAvatar(userInfo.getAvatarUrl());
user.setNickname(userInfo.getNickName());
user.setGender(userInfo.getGender());
user.setUserLevel((byte) 0);
user.setStatus((byte) 0);
user.setLastLoginTime(new Date());
user.setLastLoginIp(IpUtil.client(request));
user.setShareUserId(1);

userService.add(user);

} else {
user.setLastLoginTime(new Date());
user.setLastLoginIp(IpUtil.client(request));
if (userService.updateById(user) == 0) {
log.error(\”修改失败:{}\”, user);
return ResponseUtil.updatedDataFailed();
}
}
// token
UserToken userToken = null;
try {
userToken = UserTokenManager.generateToken(user.getId());
} catch (Exception e) {
log.error(\”微信登录失败,生成token失败:{}\”, user.getId());
e.printStackTrace();
return ResponseUtil.fail();
}
userToken.setSessionKey(sessionKey);
log.info(\”SessionKey={}\”,UserTokenManager.getSessionKey(user.getId()));
Map<Object, Object> result = new HashMap<Object, Object>();
result.put(\”token\”, userToken.getToken());
result.put(\”tokenExpire\”, userToken.getExpireTime().toString());
userInfo.setUserId(user.getId());
if (!StringUtils.isEmpty(user.getMobile())) {// 手机号存在则设置
userInfo.setPhone(user.getMobile());
}
try {
DateFormat df = new SimpleDateFormat(\”yyyy-MM-dd\”);
String registerDate = df.format(user.getAddTime() != null ? user.getAddTime() : new Date());
userInfo.setRegisterDate(registerDate);
userInfo.setStatus(user.getStatus());
userInfo.setUserLevel(user.getUserLevel());// 用户层级
userInfo.setUserLevelDesc(UserTypeEnum.getInstance(user.getUserLevel()).getDesc());// 用户层级描述
} catch (Exception e) {
log.error(\”微信登录:设置用户指定信息出错:\”+e.getMessage());
e.printStackTrace();
}
result.put(\”userInfo\”, userInfo);

log.info(\”【请求结束】微信登录,响应结果:{}\”, JSONObject.toJSONString(result));

return ResponseUtil.ok(result);
}

}

这段代码是一个微信小程序的登录接口,使用了Spring Boot框架进行开发。

  1. loginByWeixin方法:这是一个处理微信登录请求的方法。它接收一个WxLoginInfo对象作为参数,该对象包含了前端传递的code和userInfo信息。方法首先判断code和userInfo是否为空,如果为空则返回错误响应。然后调用微信SDK的getUserService().getSessionInfo(code)方法,通过code获取sessionKey和openId。接下来根据openId查询数据库中的wx_user表,如果用户不存在,则创建一个新的用户并保存到数据库中;如果用户存在,则更新最后登录时间。然后生成用户的token,并将token和用户信息返回给前端。

  2. 返回结果:将登录结果封装在一个Map对象中,包括token、tokenExpire和userInfo。最后将结果返回给前端。

2.3 代码登录流程拆解 ??

首先用户点击登录并授权开始调用wx.getUserProfile获取用户信息方法 –>checkLogin()判断用户是否登录过,没有将调用wx.login方法 获取临时登录凭证code

【微信小程序】授权登录流程解析

紧接着会通过wx.request把code传到开发者服务器,为了后续可以换取微信用户身份id。

【微信小程序】授权登录流程解析

【微信小程序】授权登录流程解析

使用临时登录凭证(code)向微信服务器发送请求,以获取用户的唯一标识(openid)和会话密钥(session_key)。

【微信小程序】授权登录流程解析

wxService:调用 auth.code2Session 接口,换取 用户唯一标识 OpenID

【微信小程序】授权登录流程解析

接下来根据openId查询数据库中的wx_user表,如果用户不存在,则创建一个新的用户并保存到数据库中;如果用户存在,则更新最后登录时间。然后生成用户的token,并将token和用户信息返回给前端。

表设计:

【微信小程序】授权登录流程解析

token和用户信息返回给前端:

【微信小程序】授权登录流程解析

登录成功通过后保存SessionId以及对应的用户身份信息

【微信小程序】授权登录流程解析

数据库储存数据:

【微信小程序】授权登录流程解析

下次再次发送登录请求时通过wx.getStorageSync()从本地缓存中同步获取指定用户信息和token的内容

【微信小程序】授权登录流程解析

再次登录时将会修改登录时间

【微信小程序】授权登录流程解析

案例演示:

【微信小程序】授权登录流程解析

再次登录时间更新:

【微信小程序】授权登录流程解析

3. 表情包存储展示(扩展)

在存储用户信息时可能有些用户名存在一些emoji小表情,在mysql中utf8编码的一个字符最多3个字节,但是一个emoji表情为4个字节,所以utf8不支持存储emoji表情。但是utf8的超集utf8mb4一个字符最多能有4字节,所以能支持emoji表情的存储。

修改编码集:

Linux系统中MySQL的配置文件为my.cnf。

Winows中的配置文件为my.ini。

【微信小程序】授权登录流程解析

注意:在创建数据库时也要选择utf8mb4

【微信小程序】授权登录流程解析

附议

源码:

【微信小程序】授权登录流程解析

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

申明:本文由第三方发布,内容仅代表作者观点,与本网站无关。对本文以及其中全部或者部分内容的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。本网发布或转载文章出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,也不代表本网对其真实性负责。

左子网 编程相关 【微信小程序】授权登录流程解析 https://www.zuozi.net/36497.html

常见问题
  • 1、自动:拍下后,点击(下载)链接即可下载;2、手动:拍下后,联系卖家发放即可或者联系官方找开发者发货。
查看详情
  • 1、源码默认交易周期:手动发货商品为1-3天,并且用户付款金额将会进入平台担保直到交易完成或者3-7天即可发放,如遇纠纷无限期延长收款金额直至纠纷解决或者退款!;
查看详情
  • 1、描述:源码描述(含标题)与实际源码不一致的(例:货不对板); 2、演示:有演示站时,与实际源码小于95%一致的(但描述中有”不保证完全一样、有变化的可能性”类似显著声明的除外); 3、发货:不发货可无理由退款; 4、安装:免费提供安装服务的源码但卖家不履行的; 5、收费:价格虚标,额外收取其他费用的(但描述中有显著声明或双方交易前有商定的除外); 6、其他:如质量方面的硬性常规问题BUG等。 注:经核实符合上述任一,均支持退款,但卖家予以积极解决问题则除外。
查看详情
  • 1、左子会对双方交易的过程及交易商品的快照进行永久存档,以确保交易的真实、有效、安全! 2、左子无法对如“永久包更新”、“永久技术支持”等类似交易之后的商家承诺做担保,请买家自行鉴别; 3、在源码同时有网站演示与图片演示,且站演与图演不一致时,默认按图演作为纠纷评判依据(特别声明或有商定除外); 4、在没有”无任何正当退款依据”的前提下,商品写有”一旦售出,概不支持退款”等类似的声明,视为无效声明; 5、在未拍下前,双方在QQ上所商定的交易内容,亦可成为纠纷评判依据(商定与描述冲突时,商定为准); 6、因聊天记录可作为纠纷评判依据,故双方联系时,只与对方在左子上所留的QQ、手机号沟通,以防对方不承认自我承诺。 7、虽然交易产生纠纷的几率很小,但一定要保留如聊天记录、手机短信等这样的重要信息,以防产生纠纷时便于左子介入快速处理。
查看详情

相关文章

猜你喜欢
发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务