使用微信小程序来实现网站的扫码登录功能

news/2024/5/13 14:46:22/文章来源:https://blog.csdn.net/weixin_45089791/article/details/126341589

使用微信小程序来实现网站的扫码登录功能

偶然间, 我发现了扫描微信小程序码就可以登录的网站, 后来也发现腾讯云的后台登录, 也是扫描一个二维码后,打开一个微信小程序后, 在小程序上点击授权,就可以登录了, 所以我就本着好奇的态度, 研究了一下这个功能是如何实现的.为此我还专门注册了一个微信小程序.

1. 准备工作
  • 首先, 我们需要注册一个自己的微信小程序, 去微信公众平台 申请, 选择个人即可, 这个功能, 无法使用测试号, 因为扫描小程序跳转的页面必须是已经上线的页面 文档地址
    在这里插入图片描述
  • 我们提交填好信息后提交申请即可.
  • 接下来说明所需技术栈, 我这里使用的Java语言, 我们需要会springboot, vue, 微信小程序开发.
2. 功能展示
  • 手机端

1660472877413530

  • pc端

2022-08-14 17.44.20

3. 登录流程时序图

在这里插入图片描述

4. 核心代码说明
  • 首先我们创建一个springboot 项目引入操作小程序的maven坐标, github地址
        <dependency><groupId>com.github.binarywang</groupId><artifactId>weixin-java-miniapp</artifactId><version>4.3.0</version></dependency>

我们需要这三个controller
在这里插入图片描述
在这里插入图片描述
主要的核心代码就在WxMaUserController

/*** 微信小程序用户接口*/
@RestController
@AllArgsConstructor
@Slf4j
@RequestMapping("/wx/user/{appid}")
public class WxMaUserController {private final WxMaService wxMaService;private final RedisService redisService;private final SysUserService sysUserService;private final TokenService tokenService;/*** 登陆接口*/@GetMapping("/login")public AjaxResult login(@PathVariable String appid, String code, String scene) {if (StringUtils.isBlank(code)) {return AjaxResult.error("empty jscode");}String key = WxConstant.WX_QRCODE_SCENE + scene;String value = redisService.getCacheObject(key) != null ? redisService.getCacheObject(key).toString() : "";if (StringUtils.isNotEmpty(value)) {redisService.setCacheObject(key, WxConstant.WX_QRCODE_SCAN, 3, TimeUnit.MINUTES);}if (!wxMaService.switchover(appid)) {throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid));}try {WxMaJscode2SessionResult session = wxMaService.getUserService().getSessionInfo(code);log.info(session.getSessionKey());log.info(session.getOpenid());//TODO 可以增加自己的逻辑,关联业务相关数据return AjaxResult.success(session);} catch (WxErrorException e) {log.error(e.getMessage(), e);return AjaxResult.error(e.toString());} finally {WxMaConfigHolder.remove();//清理ThreadLocal}}/*** <pre>* 获取用户信息接口* </pre>*/@GetMapping("/info")public AjaxResult info(@PathVariable String appid, String openId, String sessionKey,String signature, String rawData, String encryptedData, String iv, String scene) {if (!wxMaService.switchover(appid)) {throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid));}// 用户信息校验if (!wxMaService.getUserService().checkUserInfo(sessionKey, rawData, signature)) {WxMaConfigHolder.remove();//清理ThreadLocalreturn AjaxResult.error("user check failed");}String key = WxConstant.WX_QRCODE_SCENE + scene;String value = redisService.getCacheObject(key) != null ? redisService.getCacheObject(key).toString() : "";if (StringUtils.isEmpty(value)) {return AjaxResult.error(401, "验证码已过期");}// 解密用户信息WxMaUserInfo userInfo = wxMaService.getUserService().getUserInfo(sessionKey, encryptedData, iv);WxMaConfigHolder.remove();//清理ThreadLocalSysUser one = sysUserService.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getOpenId, openId));if (one == null) {SysUser sysUser = new SysUser();sysUser.setUserName(userInfo.getNickName());sysUser.setAvatarUrl(userInfo.getAvatarUrl());sysUser.setOpenId(openId);sysUserService.save(sysUser);}if (StringUtils.isNotEmpty(value)) {redisService.setCacheObject(key, WxConstant.WX_QRCODE_SUCCESS + openId, 30, TimeUnit.SECONDS);}return AjaxResult.success(userInfo);}/*** <pre>* 获取小程序码* </pre>*/@SneakyThrows@GetMapping("/getQRCode")public AjaxResult getQRCode(@PathVariable String appid) {String uuid = UUID.randomUUID().toString().replaceAll("-", "");String key = WxConstant.WX_QRCODE_SCENE + uuid;redisService.setCacheObject(key, WxConstant.WX_QRCODE_NOT_SCAN, 3, TimeUnit.MINUTES);byte[] release = wxMaService.getQrcodeService().createWxaCodeUnlimitBytes(uuid, "pages/login/login", true, "release", 430, true, (WxMaCodeLineColor) null, false);String s = Base64.encodeBase64String(release);HashMap<String, Object> map = new HashMap<>();map.put("scene", uuid);map.put("img", WxConstant.BASE64_PNG + s);return AjaxResult.success(map);}/*** 根据uuid 查询redis中当前小程序码的状态* @param appid* @param uuid* @return*/@GetMapping("/getQRStatus/{uuid}")public AjaxResult getQRStatus(@PathVariable String appid, @PathVariable String uuid) {String key = WxConstant.WX_QRCODE_SCENE + uuid;String value = redisService.getCacheObject(key) != null ? redisService.getCacheObject(key).toString() : "";AjaxResult success = AjaxResult.success();HashMap<String, String> map = new HashMap<>();if (StringUtils.isNotEmpty(value) && value.startsWith(WxConstant.WX_QRCODE_SUCCESS)) {String openId = value.split("-")[1];String token = tokenService.createToken(openId);map.put(WxConstant.QR_STATUS, WxConstant.QR_STATUS_SUCCESS);map.put(WxConstant.TOKEN, token);success.put(AjaxResult.DATA_TAG, map);} else if (StringUtils.isNotEmpty(value)) {map.put(WxConstant.QR_STATUS, value);success.put(AjaxResult.DATA_TAG, map);} else {map.put(WxConstant.QR_STATUS, WxConstant.WX_QRCODE_EXPIRED);success.put(AjaxResult.DATA_TAG, map);}return success;}}

说明:
就是利用了在生成小程序码的时候可以传递一个额外的参数:在这里插入图片描述
我们在pc端请求生成小程序码接口的时候, 生成一个全局唯一的字符串给微信接口, 并且我们将这个唯一字符串作为key, 一个状态码为value 存入redis 中

  • pc端的核心代码如下:
<template><div class="container"><div class="w-img"><el-avatar id="qrcode" :size="250" src="https://empty" @click="getImgQrCode" style="border: 8px solid #999;"class=""><img:src="qcUrl"/></el-avatar></div><div class="w-qr-status-text" v-show="isShow">{{ qcStatus }}</div></div>
</template><script setup lang="ts">import {onUnmounted, ref} from "vue";
import router from "../router";
import {getQRCode, getQRStatus} from "../api/login";
import {setToken} from "../utils/auth";const qcStatus = ref('请先扫码');
const qcUrl = ref();
const isShow = ref(true);
const time = ref()const uuid = ref();onUnmounted(() => {clearTimeout(time.value)
})const getImgQrCode = () => {getQRCode().then(res => {qcUrl.value = res.data.img;uuid.value = res.data.sceneisShow.value = truedocument.querySelector('#qrcode')!.classList.remove('w-qr-dead')clearTimeout(time.value)getStatus()})
}
const getStatus = () => {time.value = setInterval(() => {getQRStatus(uuid.value).then(res => {const {status} = res.dataif (-1 == status) {document.querySelector('#qrcode')!.className = (`${document.querySelector('#qrcode')!.className} w-qr-dead`)isShow.value = falseclearTimeout(time.value)}if (1 == status) {qcStatus.value = '已扫码,等待操作';}if (2 == status) {clearTimeout(time.value)const {token} = res.datasetToken(token)router.push({path: "/"});}})}, 2000)}getImgQrCode()
</script><style lang="scss" scoped>.container {width: 100%;height: 100vh;background-color: #333;display: flex;align-items: center;flex-direction: column;justify-content: center;.w-qr-status-text {display: flex;width: 250px;height: 48px;background-color: black;align-items: center;justify-content: center;color: #aaa;border-radius: 24px;margin-top: 10px;}.w-qr-dead:before {top: 0;left: 0;width: 100%;height: 100%;background-color: rgba(0, 0, 0, .9);border-radius: 50%;color: #fff;content: '码已过期,点击刷新';display: flex;align-items: center;justify-content: center;cursor: pointer;}
}
</style>
  • 小程序核心代码:
    • login.wxml
      <view class="w-main"><view class="w-img-pc"><image class="size-l" mode="aspectFill" src="{{titleImg}}"></image></view><text class="w-title">{{title}}</text><text class="w-desc">{{desc}}</text><t-button bindtap="getUserProfile" wx:if="{{isLogin}}" class="w-login-btn" theme='primary' block>登录</t-button>
      </view>
      
    • login.wxss
      /* pages/login/login.wxss */
      .w-main {display: flex;text-align: center;min-height: 100vh;flex-direction: column;justify-content: center;
      }
      .w-img-pc image{padding-bottom: 150rpx;width: 200rpx;height: 200rpx;
      }
      .w-title {margin-top: 2rpx;font-size: 40rpx;
      }
      .w-desc {margin-top: 10rpx;font-size: 30rpx;
      }.w-login-btn {padding-top: 100rpx;margin-left: 100rpx;margin-right: 100rpx;
      }
      
    • login.js
      // pages/login/login.js
      const request = require('../../api/login.js');
      Page({/*** 页面的初始数据*/data: {title: '欢迎来到wdhcr的小窝',desc: '请确认登录',titleImg: '../../assets/pc.png',isLogin: true,openId: '',sessionKey: '',scene: ''},/*** 生命周期函数--监听页面加载*/onLoad(options) {this.setData({scene: decodeURIComponent(options.scene)})this.getOpenId();},getOpenId() {wx.login({success: res => {console.log(res.code)request.getOpenId({ code: res.code, scene: this.data.scene ? this.data.scene : '-1'}).then(res => {this.setData({openId: res.data.openid,sessionKey: res.data.sessionKey})})}})},getUserProfile(e) {// 开发者妥善保管用户快速填写的头像昵称,避免重复弹窗wx.getUserProfile({desc: '用于完善会员资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写success: (res) => {var params = {'openId': this.data.openId,'sessionKey': this.data.sessionKey,'encryptedData': res.encryptedData,'rawData': res.rawData,'signature': res.signature,'iv': res.iv,'scene': this.data.scene ? this.data.scene : '-1','openId': this.data.openId}request.getInfo(params).then(res => {if (res.code === 200) {wx.reLaunch({url: '/pages/home/home',})} else if (res.code === 401) {this.setData({desc: res.msg,titleImg: '../../assets/laptop-error.png',isLogin: false})}})}})},/*** 生命周期函数--监听页面初次渲染完成*/onReady() {},/*** 生命周期函数--监听页面显示*/onShow() {},/*** 生命周期函数--监听页面隐藏*/onHide() {},/*** 生命周期函数--监听页面卸载*/onUnload() {},/*** 页面相关事件处理函数--监听用户下拉动作*/onPullDownRefresh() {},/*** 页面上拉触底事件的处理函数*/onReachBottom() {},/*** 用户点击右上角分享*/onShareAppMessage() {}
      })
      

以上就是小程序登录的所有核心代码了.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_893221.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python爬某Ecust教务处网站

1.背景: 某ECUST高校的教务处网站现在查成绩需要验证码了。但是家长登陆的窗口还没有使用验证码,用这个漏子来爬去一下教务处的成绩: 2.工具: Google chorme浏览器 Python 3.6.0 requests 库 PyQuery 库 lxml 库&#xff08;代码中并未用到&#xff0c;只是因为PyQuery库…

利用华为云建WordPress博客网站

一、建站要求 使用主备2台RDS服务器先使用第一台ECS云服务器建站可以用Wordpress镜像&#xff0c;但建议用运行环境镜像搭建服务器&#xff0c;然后下载wordpress软件&#xff0c;解压安装的方式单台ECS正常运行后&#xff0c;通过私有镜像的方式&#xff0c;构建第二台ECS使用…

SEO笔记(一)

1、SEO优缺点 优点&#xff1a;成本低、持久性、不需要承担“无效点击”的风险&#xff1b; 缺点&#xff1a;施工时间长、不确定性&#xff08;不能保证SEO能够达到什么效果&#xff09;、被动性&#xff08;搜索引擎算法改变会给SEO带来灾难性的后果&#xff09;。 2、搜索…

SEO笔记(二)--URL优化

1.URL简介 URL&#xff08;Uniform Resource Locator&#xff0c;统一资源定位器&#xff09;是页面的网址&#xff0c;通过URL才能访问具体的网页。URL优化时网站的六大重要环节之一&#xff0c;在决定页面相关性中有重要作用&#xff0c;而且会直接影响到收索引擎对页面的收…

SEO笔记—网页结构优化(四)

网页结构优化是页面优化的重点之一&#xff0c;它是对网页内容布局的规划&#xff0c;合理的网页结构能够有效地提高用户体验和搜索引擎的友好性。网页主要包含导航栏、栏目以及正文三部分组成&#xff0c;对网页结构的主要也是围绕这三部分进行的。 1、页面重要区域分布规律 …

国外家喻户晓的搜索引擎优化SEO工具商SEOmoz公司获$1800万融资

5.1日&#xff0c;国外著名的SEO&#xff08;搜索引擎优化&#xff09;工具商 SEOmoz 获得1800万美元融资&#xff0c;此次投资由风险投资公司 Foundry Group 和 Ignition Partners领头。关于 SEOmoz&#xff0c;目前是一个著名的seo工具提供商&#xff0c;最初为分享优化经验…

SEO笔记—网站结构(五)

网站的结构是指网站中页面之间的层次关系&#xff0c;可分为逻辑结构和物理结构&#xff0c;他直接影响搜索引擎对网站页面收录的数量和页面的权重。 1、搜索引擎首先会抓取网站中权重最大的页面&#xff08;一般是首页&#xff09;&#xff0c;然后跟踪其中的连接来抓取网站中…

sharepoint 2016 场快速配置(4)mdash;mdash;管理网站集

网站集管理 创建网站集 1. 在管理中心站点单击“创建网站集” 2. 选择相应的web应用程序&#xff0c;并设置标题&#xff0c;管理路径和首要站点的模板&#xff0c;以及网站集管理员 3. 使用powershell命令创建网站集 New-SPSite http://moss2016 -HostHeaderWebApplication…

从shenfenzheng网站获取身份证号码等信息

这个程序是最初学Beautiful Soup时&#xff0c;写的一个程序。 因为相对以前的正则什么的&#xff0c;获取一组数据还是有点麻烦的&#xff0c;这边分割&#xff0c;那边分割。程序代码也没有那么简单直观。 如图&#xff0c;是我们今天要获取数据的网页 本次我们用到的的…

JS特效教程:给网站添加鼠标点击弹出指定汉字特效

网站添加鼠标点击弹出指定汉字特效&#xff0c;就是鼠标点击站点任何位置&#xff0c;都会随机弹出我们指定的一组汉字中的一个。比如指定“文明&#xff0c;自由&#xff0c;民主&#xff0c;公正&#xff0c;和谐”等&#xff0c;点击鼠标时就会随机显示这一组的某个词语&…

中小型网站运营者的基础运营思路

对于中小型网站、尤其是企业展示型官网的运营者&#xff0c;往往技术能力有限&#xff0c;由公司的“网管”负责运营&#xff0c;这就意味着这个网管很可能对网站运营毫无概念&#xff0c;或是一知半解&#xff0c;本篇文章就是基于这个现状&#xff0c;讲述一下这种情况下的基…

揭秘全球最大网站Facebook背后的那些软件

2010年6月&#xff0c;Google公布全球Top 1000 网站。Facebook独占鳌头。 以Facebook现在的经营规模&#xff0c;诸多传统服务器的技术均将崩溃或根本无法支撑。那么面对5亿的活跃用户&#xff0c;Facebook的工程师们又将如何让网站平稳运转呢&#xff1f;伯乐在线 - 职场博客的…

2019仿笔趣阁小说网站源码(PC版+手机版+APP+采集器+教程)下载

第三套杰奇WAP小说模板&#xff0c;使用百度MIP&#xff0c;更重要的是这次使用了百度的MIP来制作模板。 1、底层程序仍然是独立版程序&#xff0c;模板样式和代码已经全部重写&#xff0c;不在有原来的代码。 2、同时本套程序已经更新过底层代码&#xff0c;本套模板中&#x…

苹果cmsv10漂亮大气响应式视频网站模板(自适应手机端)源码下载

苹果CMSV10模板&#xff0c;仿69TAN&#xff0c;黑色大气自适应视频网站模板 提供苹果CMS8X和V10模板、海洋CMS模板、菲菲2、X、3 x、5 x、红兔CMS、X模板 源代码下载链接: https://pan.baidu.com/s/1Gg4ATO1vzq5cZXt8u7YDAA 提取码: sjwg

阿里云主机搭建网站,并使外网可访问到

一、在阿里云主机搭建网站 1.连接上阿里云主机&#xff0c;在里面操作&#xff1a;&#xff08;在本地的电脑使用远程桌面连接即可&#xff0c;输入公网IP和用户密码进行连接&#xff09; 下载phpstudy&#xff08;一个类似WEB服务器的软件工具&#xff0c;搭建服务器环境&…

You-Get,多网站视频下载工具,非常方便

You-Get是一个非常优秀的网站视频下载工具。使用You-Get可以很轻松的下载到网络上的视频、图片及音乐。 按WinR键打开运行&#xff0c;输入cmd&#xff0c;再输入命令 pip install you-get&#xff0c;安装 you-get you-get 中文说明 : https://github.com/soimort/you-get/wik…

大作业rhce(网站.邮件.dns)

一.要求 二.做实验 2.1配置百度网站 1在虚拟机上建库&#xff0c;进入/etc/yum.repos.d/目录&#xff0c;编辑 baser.repo 配置文件 [baseos] namebaseos baseurl/mnt/BaseOS gpgcheck0 [appstream] nameappTream baseurl/mnt/AppStream gpgcheck0 2 在虚拟机上安装 httpd 包…

避免网站在IE6中出现‘无法打开站点,已终止操作’的JS问题

IE6在中国还占据着30%的用户&#xff0c;其中大多数网吧还是使用的IE6.0&#xff0c;所以很多网站必须一直兼容IE6下去。 如果浏览一个网站出现 无法打开站点&#xff0c;已终止操作 的故障&#xff0c;浏览器就会变成一片空白&#xff0c;而用户就会关闭网站&#xff0c;在非…

struts2+hibernate 实现B2C电子商务网站的登录 、注册中验证码的实现(源码)

下边只在注册中实现 1、首先是在Action中写出生成验证码所需的方法&#xff08;下边是在MemberAction.java中写&#xff09; [java] view plain copy print ? package www.csdn.dbshop.action; import org.apache.struts2.ServletActionContext; import www.csdn.dbshop…

实际采用 FleaPHP 的网站

下面都是采用 FleaPHP 框架开发的网站列表&#xff0c;如果发现无效连接请在留言。 如果你有采用 FleaPHP 开发的网站&#xff0c;并且愿意公开网址&#xff0c;可以发邮件到 dualface (at) gmail.com 需要提供的信息包括网站名称和连接地址&#xff0c;以及简单的介绍文字。…