微信小程序登录

最近项目中需要微信登录,包括网页微信登录,小程序微信登录,App微信登录。本文先记录小程序微信登录。


微信小程序登录流程涉及到三个角色:小程序、开发者服务器、微信服务器

文章目录

  • 微信小程序登录
  • 三者交互步骤如下
  • 登录流程
  • controller
    • 用于接收用户请求,校验签名,并生成skey,存储skey、openid等数据
    • WechatUtil
  • 微信小程序

三者交互步骤如下

第一步:小程序通过wx.login()获取code。
第二步:小程序通过wx.request()发送code到开发者服务器。
第三步:开发者服务器接收小程序发送的code,并携带appid、appsecret(这两个需要到微信小程序后台查看)、code发送到微信服务器。
第四步:微信服务器接收开发者服务器发送的appid、appsecret、code进行校验。校验通过后向开发者服务器发送session_key、openid。
第五步:开发者服务器自己生成一个skey(自定义登录状态)与openid、session_key进行关联,并存到数据库中(mysql、redis等)。
第六步:开发者服务器返回生成skey(自定义登录状态)到小程序。
第七步:小程序存储skey(自定义登录状态)到本地。
第八步:小程序通过wx.request()发起业务请求到开发者服务器,同时携带skey(自定义登录状态)。
第九步:开发者服务器接收小程序发送的skey(自定义登录状态),查询skey在数据库中是否有对应的openid、session_key。
第十步:开发者服务器返回业务数据到小程序


登录流程时序如下:

登录流程

第一步:小程序通过wx.login()获取code。
第二步:小程序通过wx.request()发送code到开发者服务器。
第三步:开发者服务器接收小程序发送的code,并携带appid、appsecret(这两个需要到微信小程序后台查看)、code发送到微信服务器。
第四步:微信服务器接收开发者服务器发送的appid、appsecret、code进行校验。校验通过后向开发者服务器发送session_key、openid。
第五步:开发者服务器自己生成一个skey(自定义登录状态)与openid、session_key进行关联,并存到数据库中(mysql、redis等)。
第六步:开发者服务器返回生成skey(自定义登录状态)到小程序。
第七步:小程序存储skey(自定义登录状态)到本地。

controller

用于接收用户请求,校验签名,并生成skey,存储skey、openid等数据

代码如下(示例):

package cn.lastwhisper.springbootwx.controller;import cn.lastwhisper.springbootwx.common.GlobalResult;
import cn.lastwhisper.springbootwx.mapper.UserMapper;
import cn.lastwhisper.springbootwx.pojo.User;
import cn.lastwhisper.springbootwx.common.WechatUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;import java.util.Date;
import java.util.UUID;/*** @author lastwhisper* @desc* @email gaojun56@163.com*/
@Controller
public class UserController {@Autowiredprivate UserMapper userMapper;/*** 微信用户登录详情*/@PostMapping("wx/login")@ResponseBodypublic GlobalResult user_login(@RequestParam(value = "code", required = false) String code,@RequestParam(value = "rawData", required = false) String rawData,@RequestParam(value = "signature", required = false) String signature,@RequestParam(value = "encrypteData", required = false) String encrypteData,@RequestParam(value = "iv", required = false) String iv) {// 用户非敏感信息:rawData// 签名:signatureJSONObject rawDataJson = JSON.parseObject(rawData);// 1.接收小程序发送的code// 2.开发者服务器 登录凭证校验接口 appi + appsecret + codeJSONObject SessionKeyOpenId = WechatUtil.getSessionKeyOrOpenId(code);// 3.接收微信接口服务 获取返回的参数String openid = SessionKeyOpenId.getString("openid");String sessionKey = SessionKeyOpenId.getString("session_key");// 4.校验签名 小程序发送的签名signature与服务器端生成的签名signature2 = sha1(rawData + sessionKey)String signature2 = DigestUtils.sha1Hex(rawData + sessionKey);if (!signature.equals(signature2)) {return GlobalResult.build(500, "签名校验失败", null);}// 5.根据返回的User实体类,判断用户是否是新用户,是的话,将用户信息存到数据库;不是的话,更新最新登录时间User user = this.userMapper.selectById(openid);// uuid生成唯一key,用于维护微信小程序用户与服务端的会话String skey = UUID.randomUUID().toString();if (user == null) {// 用户信息入库String nickName = rawDataJson.getString("nickName");String avatarUrl = rawDataJson.getString("avatarUrl");String gender = rawDataJson.getString("gender");String city = rawDataJson.getString("city");String country = rawDataJson.getString("country");String province = rawDataJson.getString("province");user = new User();user.setOpenId(openid);user.setSkey(skey);user.setCreateTime(new Date());user.setLastVisitTime(new Date());user.setSessionKey(sessionKey);user.setCity(city);user.setProvince(province);user.setCountry(country);user.setAvatarUrl(avatarUrl);user.setGender(Integer.parseInt(gender));user.setNickName(nickName);this.userMapper.insert(user);} else {// 已存在,更新用户登录时间user.setLastVisitTime(new Date());// 重新设置会话skeyuser.setSkey(skey);this.userMapper.updateById(user);}//encrypteData比rowData多了appid和openid//JSONObject userInfo = WechatUtil.getUserInfo(encrypteData, sessionKey, iv);//6. 把新的skey返回给小程序GlobalResult result = GlobalResult.build(200, null, skey);return result;}
}

WechatUtil

代码如下(示例):

package cn.lastwhisper.springbootwx.common;/*** Create by eval on 2019/3/20*/import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.shiro.codec.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.AlgorithmParameters;
import java.security.Security;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;/*** @ClassName WechatUtil* @Description TODO* @Author eval* @Date 9:44 2019/3/20* @Version 1.0*/
public class WechatUtil {public static JSONObject getSessionKeyOrOpenId(String code) {String requestUrl = "https://api.weixin.qq.com/sns/jscode2session";Map<String, String> requestUrlParam = new HashMap<>();// https://mp.weixin.qq.com/wxopen/devprofile?action=get_profile&token=164113089&lang=zh_CN//小程序appIdrequestUrlParam.put("appid", "小程序appId");//小程序secretrequestUrlParam.put("secret", "小程序secret");//小程序端返回的coderequestUrlParam.put("js_code", code);//默认参数requestUrlParam.put("grant_type", "authorization_code");//发送post请求读取调用微信接口获取openid用户唯一标识JSONObject jsonObject = JSON.parseObject(HttpClientUtil.doPost(requestUrl, requestUrlParam));return jsonObject;}public static JSONObject getUserInfo(String encryptedData, String sessionKey, String iv) {// 被加密的数据byte[] dataByte = Base64.decode(encryptedData);// 加密秘钥byte[] keyByte = Base64.decode(sessionKey);// 偏移量byte[] ivByte = Base64.decode(iv);try {// 如果密钥不足16位,那么就补足.  这个if 中的内容很重要int base = 16;if (keyByte.length % base != 0) {int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);byte[] temp = new byte[groups * base];Arrays.fill(temp, (byte) 0);System.arraycopy(keyByte, 0, temp, 0, keyByte.length);keyByte = temp;}// 初始化Security.addProvider(new BouncyCastleProvider());Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");parameters.init(new IvParameterSpec(ivByte));cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化byte[] resultByte = cipher.doFinal(dataByte);if (null != resultByte && resultByte.length > 0) {String result = new String(resultByte, "UTF-8");return JSON.parseObject(result);}} catch (Exception e) {}return null;}
}

微信小程序

pages/me/me.js
Page({/*** 页面的初始数据*/data: {hasUserInfo: false,userInfo: null},onLoad: function() {// 页面加载时使用用户授权逻辑,弹出确认的框  this.userAuthorized()},userAuthorized() {wx.getSetting({success: data => {if (data.authSetting['scope.userInfo']) {wx.getUserInfo({success: data => {this.setData({hasUserInfo: true,userInfo: data.userInfo})}})} else {this.setData({hasUserInfo: false})}}})},onGetUserInfo(e) {const userInfo = e.detail.userInfoif (userInfo) {// 1. 小程序通过wx.login()获取codewx.login({success: function(login_res) {//获取用户信息wx.getUserInfo({success: function(info_res) {// 2. 小程序通过wx.request()发送code到开发者服务器wx.request({url: 'http://localhost:8080/wx/login',method: 'POST',header: {'content-type': 'application/x-www-form-urlencoded'},data: {code: login_res.code, //临时登录凭证rawData: info_res.rawData, //用户非敏感信息signature: info_res.signature, //签名encrypteData: info_res.encryptedData, //用户敏感信息iv: info_res.iv //解密算法的向量},success: function(res) {if (res.data.status == 200) {// 7.小程序存储skey(自定义登录状态)到本地wx.setStorageSync('userInfo', userInfo);wx.setStorageSync('skey', res.data.data);} else{console.log('服务器异常');}},fail: function(error) {//调用服务端登录接口失败console.log(error);}})}})}})this.setData({hasUserInfo: true,userInfo: userInfo})}}})

SpringBoot项目实现微信小程序登录步骤相关推荐

  1. SpringBoot实现微信小程序登录功能

    SpringBoot实现微信小程序登录 微信小程序登录流程 登录流程图 前端代码 后端代码 微信小程序登录流程 微信小程序官方文档:微信小程序官方文档 第一次学习微信小程序的登录,以前也好奇微信小程序 ...

  2. SpringBoot中,使用WxJava SDK 实现微信小程序登录

    概述 WxJava SDK是一个比较实用的第三方微信开发 Java SDK github地址:https://github.com/Wechat-Group/WxJava SpringBoot项目中使 ...

  3. springBoot+微信小程序登录

    微信小程序登录流程 微信小程序登录流程涉及到三个角色:小程序.开发者服务器.微信服务器 三者交互步骤如下: 第一步:小程序通过wx.login()获取code. 第二步:小程序通过wx.request ...

  4. 基于java+SpringBoot+HTML+Mysq+微信小程序+小说阅读网站

     详细功能设计:请点击下面链接查看 基于java+SpringBoot+HTML+Mysq+微信小程序+小说阅读网站_哔哩哔哩_bilibili 源码+论文获取: 源码+论文获取请私信获取 基于Spr ...

  5. ​微信小程序开发难?资深大V教您微信小程序制作步骤和方法​

    ​微信小程序开发难?资深大V教您微信小程序制作步骤和方法​ 一.登录微信公众平台 就能在菜单"开发"---"基本配置"中看到小程序的AppID了,小程序的 Ap ...

  6. 【SpringBoot学习】39、SpringBoot 集成 wxJava 微信小程序:订单支付

    文章目录 SpringBoot 集成 wxJava 微信小程序:订单支付 1.整合 wxJava 小程序 2.支付配置类 3.application.yml 配置 4.授权登录流程 5.uniapp ...

  7. 小程序---365笔记第11天---微信小程序登录接入

    接入前的准备工作参考文档:微信小程序登录接入 (必做) 登录逻辑:小程序登录逻辑梳理 使用插件参考文档:https://developers.weixin.qq.com/miniprogram/dev ...

  8. 用Spring Boot完成微信小程序登录

    使用Spring Boot完成微信小程序登录 由于微信最近的版本更新,wx.getUserInfo()的这个接口即将失效,将用wx.getUserProfile()替换,所以近期我也对自己的登录进行更 ...

  9. 微信小程序登录功能的前端设计与实现

    导语 | 登录/注册这模块就像个冰山,我们通常以为它就是「输入账号密码,就完成登录了」,但实际下面还有各种需要考虑的问题.作为应用的基础能力,登录/注册的设计需要有足够的健壮性,避免出现全站性阻塞.同 ...

  10. 微信小程序登录 + 基于token的身份验证

    官方时序图如下: https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html 图里其实说的很清 ...

最新文章

  1. MFC中进度条控件的使用方法
  2. 米家扫拖一体机器人重置键_全面升级——米家扫拖机器人1T体验
  3. 整理Linux查看系统日志的一些经常使用命令
  4. zookeeper集群部署 精简版本
  5. mysql using btree_mysql 索引中的USING BTREE 的意义
  6. 报表工具之JasperReports+iReport(1)
  7. Quartz + Oracle 分布式Job实现
  8. 远卓:数字化转型的精益化思考
  9. 最全jar包下载地址
  10. 计算机加域后数据库无法登录,客户端多台计算机登录域失败,显示如下
  11. 卡内基梅隆计算机专业排名,2019年卡内基梅隆大学计算机专业排名多少?
  12. 天融信网络知识小百科——第六回:如何为交换机选配光模块?
  13. [原创] Python3.6+request+beautiful 半次元Top100 爬虫实战,将小姐姐的cos美图获得
  14. node生成唯一设备id(node-machine-id)
  15. 用计算机弹奏七月上,七月上歌词背后的故事 七月上背景故事介绍
  16. css百分比定位和百分比尺寸
  17. azkaban详细使用教程
  18. learn words by steps 13 英语单词
  19. 2021-2027全球与中国汽车电动多回转执行器市场现状及未来发展趋势
  20. 应用现代化中的弹性伸缩

热门文章

  1. Uphone开发心得
  2. 音视频同步、网络抖动
  3. 项目管理能力提升四要素
  4. thinkphp 5 验证码错误,可能与session保存路径不同有关
  5. 「产品读书」精益创业
  6. java画图曲线_绘图(直线和曲线)
  7. 医院时钟系统(网络授时设备)设计方案
  8. python中find函数的使用方法_详解Python中find()方法的使用
  9. 不动产租赁运营平台,为不动产租赁提供强劲的运营支持
  10. 博主的EMNLP2021合作工作已公开:TransPrompt——基于Prompt和迁移学习的小样本文本分类,欢迎阅读与引用