小程序实现微信登录Java后端(一)--前端实现

2023-11-20

目录

一、概述

二、登录流程

三、前端代码

四、解读前端代码

1、登录部分

2、检查当前用户是否已登录

3、小程序启动时校验登录

五、阶段性小结


一、概述

最近终于有时间去搞一下准备参加比赛的小程序,小程序一开始设计的是使用邮箱登录,老师建议直接实现微信登录,更加方便,以前没有搞过,这次试一下。

网上实现小程序微信登录的教程不是很多,其中使用Java后台的更是少之又少,大部分是基于node.js的,而且网上的教程大部分代码缺头少尾,让人摸不着头脑,所以我打算写一个思路清晰一些的教程。

首先附上微信官方文档给的微信登录流程: 

先理解一下几个概念:

code:是小程序通过wx.login()获取的,也是用户注册、登录时,前端向后端发送登录凭证。

openid:是后端使用code作为参数,调用微信接口服务获得的。openid是每个微信用户在一个特定的小程序或公众号中的唯一标识符,可以用来区分不同用户。

session_key:也是后端使用code作为参数,调用微信接口服务获得的。session_key是与当前用户会话相关的密钥,用于进行数据加密和解密。其重要性不及openid,可以选择性使用。

开发者服务器:跑后端代码的服务器。

微信接口服务:微信官方提供的API,开发者可以调用这个API获得 openid 和 session_key 。

二、登录流程

从微信官方文档可以看出,具体流程分为一下几点:

  1. 在小程序前端,使用 wx.login 获取用户的临时登录凭证 code。
  2. 将获取到的 code 使用 wx.request 发送给后端服务器。
  3. 在后端服务器中,使用这个 code 调用微信接口服务得到用户的 session_key 和 openid。可以使用微信提供的登录接口或者第三方库来实现这一步骤。
  4. 将获取到的 session_key 和 openid 存储到后端数据库中,这样后面可以根据这些信息来识别和关联用户。
  5. 在后端服务器中,根据 openid 将用户的其他信息存储到数据库中。注意,要确保用户的 openid 是唯一的,可以使用 openid 作为用户的唯一标识。
  6. 存储完用户信息后,后端可以生成一个用户的 token 并返回给小程序前端。小程序前端可以将这个token存储在storage和本地缓存中。
  7. 后续的请求可以携带这个 token 进行身份验证和授权。

注意微信新出的规定:

从大概2022年十月份起,不允许小程序在获得用户微信登录授权后,直接通过弹窗方式询问是否可以获得用户的微信头像和昵称。好像是因为好些小程序设置了,如果用户禁止小程序使用头像昵称,小程序就会阻止用户登录,即使用户已经授权了微信登录。官方好像认为这侵犯了用户的权益。(好像是这样,我也不太确定哈)

以前的规定是:如果需要存储用户的其他信息(如昵称、头像等),在小程序前端使用 wx.getUserInfo 获取用户信息。

现在的规定是:当小程序需要让用户完善个人资料时,可以通过微信提供的头像昵称填写能力快速完善。

具体见官方文档 头像昵称填写 | 微信开放文档

后面的文章中,我会讨论一下,在新规定下怎么样获取微信用户头像昵称。

了解完基本流程后,开发者应该获取两个必要的东西,后面用得到:

  1. AppID(小程序ID)  
  2. AppSecret(小程序密钥)  

登录进入 微信公众平台 开发-开发管理-开发者id 即可看到。

这里注意,你微信开发者工具里的 AppID,和你在官网拿到的 AppID,还有保存在后端的 AppID要保持一致,不然后面会出现离谱的错误。还有一点,就是 AppSecret 一定要和 AppID 是同一个小程序的,一定要注意!!

注意,修改appid直接在小程序目录下的project.config.json中修改即可。 

经测试,如果直接在微信开发者工具>设置>项目设置>基本信息>appId 修改,project.config.json中的appid不会改变。

而直接在project.config.json中修改,上图中开发者工具的appid会随之修改。

三、前端代码

前端代码的话,我是参考了微信小程序实现用户登录(详)_微信小程序登录_灵魂学者的博客-CSDN博客这篇博客写的,这位大佬的后端是基于node的,但是他的思路是一种循序渐进式的,如果没有耐心看完的话,很可能到一半就崩溃了哈哈哈。

前端代码如下:

// app.js
App({
  globalData: {
    baseAPI: "http://localhost:8081", //后端运行端口号
    token: null //微信登陆token
  },

  onLaunch: function () {
    this.checkLogin(res => {
      console.log('is_login : ', res.is_login);
      if (!res.is_login) {
        this.login();
      }
    })
  },


  //微信登录逻辑
  login: function () {
    let _this = this
    wx.login({
      success: (res) => {
        //console.log("code: " + res.code);
        wx.request({
          url: _this.globalData.baseAPI + "/wxlogin",
          header: {
            'content-type': 'application/json;charset=UTF-8'
          },
          method: 'POST',
          data: {
            code: res.code
          },
          success: (res) => {
            console.log("token : " + res.data.data)
            _this.globalData.token = res.data.data
            wx.setStorage({
              key: 'token',
              data: res.data.data
            })
          },
          fail: (error) => {
            console.error("QwQ请求失败:", error);
            wx.showToast({
              title: '请求失败',
              icon: 'none',
              duration: 2000
            });
          }
        })
      }
    })
  },


//检查是否登录
  checkLogin: function (callback) {
    let _this = this
    var token = _this.globalData.token
    if (!token) {
      token = wx.getStorageSync('token')
      if (token) {
        _this.globalData.token = token
      } else {
        callback({
          is_login: false
        })
      }
    }
    wx.request({
      url: _this.globalData.baseAPI + "/checkwxlogin",
      data: {
        token: token
      },
      success: (res) => {
        callback({
          is_login: res.data.code == 0 ? true : false 
        })
      }
    })
  },
})

因为微信登录是你打开小程序的时候,就要弹出来的,所以上面的代码要写在 app.js 里面。

四、解读前端代码

1、登录部分

login: function () {
    let _this = this
//调用wx.login接口,获取code,即下面的res.code
    wx.login({
      success: (res) => {
        //console.log("code: " + res.code);
        wx.request({
          url: _this.globalData.baseAPI + "/wxlogin", //调用后端接口
          header: {
            'content-type': 'application/json;charset=UTF-8'
          },
          method: 'POST',
          data: {
            code: res.code  //以post方式向后端发送code
          },
        //从后端接口得到的响应,即res.data
          success: (res) => {
            console.log("token : " + res.data.data); //后端返回的token保存在res.data.data中
            _this.globalData.token = res.data.data // 将token保存至全局 globalData
            wx.setStorage({  // 将token保存在storage本地缓存中
              key: 'token',
              data: res.data.data
            })
          },
          fail: (error) => {
            // 输出错误信息到控制台或日志
            console.error("QwQ请求失败:", error);          
            // 弹出提示框显示错误信息
            wx.showToast({
              title: '请求失败',
              icon: 'none',
              duration: 2000
            });
          }
        })
      }
    })
  }

注意上面 token 令牌的生成:后端使用 code 调用微信接口服务得到的用户的 session_key 和 openid,将 openid 经过加密变换或者结合时间戳的方式生成的,后面的文章会介绍到。

2、检查当前用户是否已登录

 checkLogin: function (callback) {
    let _this = this 
    var token = _this.globalData.token  //尝试从全局变量中获取token
    if (!token) {  //全局变量中没有
      token = wx.getStorageSync('token')  // 再试试从storage缓存中获取token
      if (token) {  //storage缓存中有
        _this.globalData.token = token
      } else {  //storage缓存也没有
        callback({
          is_login: false  //回调函数,设置登录状态为 :未登录
        })
      }
    }
    // 全局变量中有token,则向后端发送请求检验token是否存在
    wx.request({
      url: _this.globalData.baseAPI + "/checkwxlogin",
      data: {
        token: token
      },
      success: (res) => {
        //console.log(res);
        callback({
          is_login: res.data.code == 0 ? true : false  //三元表达式判断,如果res.data.code==0,则赋值is_login为true;其他,则赋值is_login为false
        })
      }
    })
  },
})

3、小程序启动时校验登录

  onLaunch: function () {
    // 小程序启动时检查用户是否登录
    this.checkLogin(res => {
      console.log('is_login : ', res.is_login);
      // 未登录,则调用login()函数
      if (!res.is_login) {
        this.login();
      }
    })
  }

五、阶段性小结

实现微信登录的前端部分已经实现好了,后续文章会继续介绍如何用Java写后端逻辑、获得用户头像昵称等,尽情期待……

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

小程序实现微信登录Java后端(一)--前端实现 的相关文章

  • java.lang.NoClassDefFoundError:HttpSessionListener

    我正在尝试部署一场我没有编写的战争 但我在日志中收到此错误 java lang NoClassDefFoundError HttpSessionListener 我知道 HttpSessionListener 位于servlet api j
  • 无法从 TemporalAccessor 获取 OffsetDateTime

    当我这样做时 String datum 20130419233512 DateTimeFormatter formatter DateTimeFormatter ofPattern yyyyMMddHHmmss withZone ZoneI
  • 按对象值分组,统计后按最大对象属性设置组键

    我设法使用 Java 8 Streams API 编写了一个解决方案 该解决方案首先按对象 Route 的值对列表进行分组 然后计算每组中的对象数量 它返回一个映射 Route gt Long 这是代码 Map
  • 文件保存在文件系统中 VS 保存在数据库中

    我正在设计一个 servlet 或 Struts2 中的操作 用于文件 图像 文档等 下载 但我想知道哪种更好的方法可以将文件保留在文件系统和数据库中 只需保留文件的路径或将文件保留在数据库中 如 BLOB 我知道当我查询数据库时 哪里的
  • (Java) 在 Mac OS X 上以编程方式访问“系统根目录”下的 SSL 证书

    我正在编写一个 Java 应用程序 它可以通过远程 Https 站点进行 REST Api 调用 远程站点由受信任的证书签名 它在 Windows 上运行良好 但由于 SSL 证书问题 在 OS X 上运行时遇到问题 我做了一些挖掘 发现原
  • 从 org.w3c.dom.Node 获取 Xpath

    我可以从 org w3c dom Node 获取完整的 xpath 吗 假设当前节点指向 xml 文档中间的某个位置 我想提取该元素的 xpath 我正在寻找的输出 xpath 是 parent child1 chiild2 child3
  • Java 泛型和数字类型

    我想创建一个通用方法来有效地执行此操作 class MyClass static
  • 如何减少 JSF 中的 javax.faces.ViewState

    减少 JSF 中视图状态隐藏字段大小的最佳方法是什么 我注意到我的视图状态约为 40k 这会在每次请求和响应时下降到客户端并返回到服务器 特别是到达服务器时 这对用户来说会显着减慢 我的环境 JSF 1 2 MyFaces Tomcat T
  • 如何在 Spring Boot 中创建 Apache POI Excel 视图配置

    当我想使用 Spring Boot Web 将数据导出到 Excel 时遇到问题 我使用 Thymeleaf 作为模板引擎 由 Spring Boot 自动配置 但是当我在附加配置中添加 XmlViewResolver 时 由 XmlVie
  • JSP 作为电子邮件模板

    有没有办法发送 MIME 电子邮件 其中电子邮件正文源自 JSP 我需要使用 Javamail 发送一封电子邮件 其中包含一个表格 我认为如果我可以使用 JSP 来完成所有格式设置和布局 将会很方便 在这个线程中 Java 电子邮件模板的建
  • 在openjdk:7-jre-alpine docker上如何安装python 3.6

    直到大约一周前 我才在 java 图像上成功使用 python 3 6 脚本 如下所示 FROM openjdk 7 jre alpine RUN apk update apk upgrade apk add no cache bash a
  • 线程睡眠阻止我的 Swing 应用程序执行

    我的应用程序发生的事情是有道理的 但我不知道如何修复它 以下是我的应用程序功能的简要描述 计时器窗口应显示在屏幕右下角并显示实时时间 一小时后 它应该执行一些操作 我还没有决定该操作 我面临的问题是定时器 java当我刷新实时计时器的秒数时
  • WebSocketStompClient 将无法连接到 SockJS 端点

    我正在尝试新的 从版本 4 2 开始 java STOMP 客户端支持 我的出发点是入门指南 使用 WebSocket 构建交互式 Web 应用程序 http spring io guides gs messaging stomp webs
  • Spring Boot如何加入自定义查询

    我需要创建一个端点 该端点按州返回人口普查数据以及城市列表 我目前使用两个端点来获取此数据 目前回应 自定义查询一 censusByState id 1 code 11 name Rond nia statePopulation 18152
  • 为什么 HttpServletRequest 输入流为空?

    我有这段代码 我从请求输入流读取输入并使用 JacksonMapper 转换为 POJO 它在具有 guice 支持的 jetty 7 容器中运行 Override protected void doPost HttpServletRequ
  • 在 Java 服务器中验证 Windows 用户

    我正在开发一个用 Java 编写的服务器和一个在同一网络上的 Windows 计算机上运行的客户端 用 Net 编写的桌面应用程序 我希望进行一些基本身份验证 以便服务器可以确定运行客户端的用户的用户名 而不需要用户在客户端中重新输入其 W
  • 如果所有类不在同一个包中,Spring @autowired 不起作用

    我有四个包裹 com spring org Files HomeController java com spring org dao Files SubscriberDao java SubscriberDaoImpl java com s
  • RecyclerView 适配器的 Kotlin 泛型

    我正在尝试编写一个通用的 recyclerview 适配器 我找到了几个例子 然而 仍然无法弄清楚如何实现通用适配器 我写的代码是 open abstract class BaseAdapter
  • 根据 Java 环境变量中的值创建使用 @JsonIgnore 的自定义注释

    我需要创建一个新的注释 用于在环境变量设置时忽略输出 JSON 文件中的字段var false 我尝试使用JsonAnnotationIntrospector 但无法获得预期的输出 public class Vehicle String v
  • 在Java的System.out中以表格格式输出

    我正在从数据库获取结果 并希望将数据作为 Java 标准输出中的表输出 我尝试过使用 t 但我想要的第一列的长度变化很大 有没有办法将其显示在类似输出的漂亮表格中 Use System out format http java sun co

随机推荐

  • 数据库初级入门sqlite3版本

    0 数据库大纲 数据库是什么 如何在在命令行使用SQL语句操作数据库 如何在C C 程序中操作数据库 1 数据库和数据库管理系统及数据库系统 数据库是一个存储数据 电子化表格 的仓库 数据库 简单来说可以看做是一个电子化的文件柜 gt 存储
  • vue element select下拉框树形多选

    components 文件下新建 SelectTree文件 index vue SelectTree index vue
  • 中关村十大AI研究院

    雷刚 发自 凹非寺 量子位 报道 公众号 QbitAI 不知你是否有同样的困惑 最近 秋季校招正在接近尾声 但意外不少非应届同学也关注起未来实习的话题 对于有志于投身AI研发的同学 有没有一些既能发论文 又贴进产业前沿 还比较近的实习机构
  • Unity3D的四种坐标系

    1 World Space 世界坐标 我们在场景中添加物体 如 Cube 他们都是以世界坐标显示在场景中的 transform position可以获得该位置坐标 2 Screen Space 屏幕坐标 以像素来定义的 以屏幕的左下角为 0
  • Wireshark抓包及DNS报文分析

    Wireshark抓包及DNS报文分析 来来来 点我进行5分钟视频学习 冲冲冲 一 抓包整体描述 第一行 帧Frame 2 指的是要发送的数据块 其中 所抓帧的序号为2 捕获字节数等于传送字节数 696字节 第二行 以太网 有线局域网技术
  • java正则表达式的语法详解及常用方法

    一 实例 今天在实现一个功能时遇到了这样一个问题 及接口传过来一个字符串 我需要判断它是一个区间还是一段文字并对其做分别处理 这里面的问题就在于我怎么去判断区间 按照数学规律区间可分为以下几种情况 M M N N N M N M N N N
  • 计算机网络重点知识(期末考研复习)

    点个关注 更多精彩持续更新为考研和期末助力 一起加油 计算机网络 第一章 思维导图 概述 计算机网络的主要性能指标 计算机网络的体系结构 OSI RM模型 TCP IP 两种模型对比 第二章 思维导图 数据通信主要指标与信道极限容量 多路通
  • java8新特性学习笔记

    使用lambda表达式排序 Collections sort temp String a String b gt return b compareTo a Collections sort temp String a String b gt
  • Camera2拍照时部分机型非常暗

    一 问题描述 1 部分手机在弱光环境下不管什么分辨率 预览和拍出来的照片都非常的暗 2 部分手机在弱光环境下 预览分辨率1920x1080 输出图片分辨率1920x1080时 预览和拍出来的照片亮度比较亮 但是在预览分辨率1920x1080
  • 重现U盘文件

    U盘中毒了 查毒后发现U盘空间还在 但是就是无法查看里面的文件 在 工具 gt 文件夹选项 中设置成 显示系统文件夹中的内容 去掉 隐藏受保护的操作系统文件 推荐 以及设置成 显示所有文件和文件夹 也不能正常显示 最近遇到很多优盘中的文件夹
  • 图像特征提取技术

    目 录 前 言 基于颜色的特征提取 1 颜色空间 2 直方图以及特征提取 基于纹理的特征提取 1 灰度共生矩阵 2 tamura纹理 基于深度神经网络的图像处理 前 言 图像特征提取属于图像分析的范畴 是数字图像处理的高级阶段 本文将从理论
  • SeleniumLibrary4.5.0 关键字详解(三)

    SeleniumLibrary4 5 0 关键字详解 三 库版本 4 5 0 库范围 全局 命名参数 受支持 简介 SeleniumLibrary是Robot Framework的Web测试库 本文档说明了如何使用SeleniumLibra
  • 获取对象Object的长度

    获取对象的长度 obj id 1 id2 1 id3 1 id4 1 id5 1 id6 1 id7 1 id8 1 id9 1 id10 1 let i Object keys this obj length console log i
  • 嵌入式linux 搭建L2TP+IPSEC客户端

    搭建L2TP IPSEC客户端需要对应的源码 xl2tpd 1 3 10和openswan 还需要一些依赖的库 gmp libpcap 一 安装openswan 安装依赖库gmp 6 1 2 1 下载 https gmplib org DO
  • C#操作SqlServer数据库,以及其常用的对象

    C 操作SQL Server数据库 1 概述 ado net提供了丰富的数据库操作 这些操作可以分为三个步骤 第一 使用SqlConnection对象连接数据库 第二 建立SqlCommand对象 负责SQL语句的执行和存储过程的调用 第三
  • 服务器备案问题解决思考?

    大家和我一样有没有在项目上线之后遇到服务器需要备案的问题呢 遇到这个问题的原因 域名没有备案 可是我发现我域名本案后还是无法通过域名直接解析到服务器80端口 所以我百度后发现 服务器竟然也要备案 而且备案步骤 手续与域名备案相比是真的麻烦
  • Docker搭建mysql主从

    目录 1 安装配置master 1 1 运行mysql容器 1 2 更新基础软件和安装vim 1 3 编辑配置文件 1 4 创建用户并授权 用于再主从库之间同步数据 2 slave数据库安装配置 2 1 运行容器 2 2 进入容器内部 2
  • JavaWeb的高级、Listener监听器--Servlet事件

    一 学习目标 1 Listener监听器 2 Listener监听器作用 3 Listener监听器的创建与销毁 二 重点知识 1 Listener监听器 Filter和Listener是Servlet规范中的两个高级特性 不同于Servl
  • vue项目打包后如何本都部署访问

    npm run build生成dist项目后 在windows部署访问 方式一 1 新建一个文件夹 进入目录后打开cmd 输入npm init y 2 输入 npm i express s 是用于在 Node js 项目中安装 Expres
  • 小程序实现微信登录Java后端(一)--前端实现

    目录 一 概述 二 登录流程 三 前端代码 四 解读前端代码 1 登录部分 2 检查当前用户是否已登录 3 小程序启动时校验登录 五 阶段性小结 一 概述 最近终于有时间去搞一下准备参加比赛的小程序 小程序一开始设计的是使用邮箱登录 老师建