当前位置: 首页 > news >正文

基于微信公众号(服务号)实现扫码自动登录系统功能

微信提供了两种方法都可以实现扫描登录。

一种是基于微信公众平台的扫码登录,另一种是基于微信开放平台的扫码登录。

两者的区别:

微信开放平台需要企业认证才能注册(认证费用300元,只需要认证1次,后续不再需要进行缴费年审)。

微信公众平台需要认证微信服务号(认证费用300元/年),才能进行扫码登录的开发。

本文主要介绍的是微信公众平台中的扫码登录。

微信公众号在线开发文档:微信公众平台开发概述 | 微信开放文档

目录

一、应用场景

二、实现原理

 三、需要用到的接口

(1)获取Access token

(2)生成带参数的二维码

(3)接收事件推送

四、核心部分代码

(1)获取access_token

(2)获取临时二维码

(3)微信推送事件方法

(4)request请求转换为Map方法

(5)检查微信登录状态

五、你可能会遇到的问题

(1)填写服务配置可能会遇到的问题

(2)本地正常,服务器上无法调用

六、结语


一、应用场景

我在我的网站中实现了这个功能,只需要使用微信扫描并关注公众号,即可实现自动登录。

在线体验地址:https://www.ewbang.com/community/login

首次扫码登录需要先进行关注公众号,后续只需要使用微信扫码即可完成自动登录。

注:你需要准备一个已经认证过的公众号或者测试号

二、实现原理

大致流程

1、用户访问微信快速登录页面,生成带参数的二维码。

2、监听微信推送事件(订阅或者扫码)

3、用户扫码会有两种情况:

① 用户初次关注公众号(订阅事件subscribe),根据时间返回的OpenID进行查询,如果系统中存在此用户,直接调用系统登录方法,否则创建默认账号并绑定OpenID,再调用系统登录方法。

② 用户之前关注过工作号(扫码事件SCAN),根据时间返回的OpenID进行查询,如果系统中存在此用户,直接调用系统登录方法,否则创建默认账号并绑定OpenID,再调用系统登录方法。

4、根据参数查询用户登录状态(轮询),登录成功之后,重定向到指定页面。

运行流程图(参考)

 三、需要用到的接口

(1)获取Access token

https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html

(2)生成带参数的二维码

https://developers.weixin.qq.com/doc/offiaccount/Account_Management/Generating_a_Parametric_QR_Code.html

(3)接收事件推送

https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_event_pushes.html

这里只处理订阅事件和扫码事件即可。

四、核心部分代码

用到的部分依赖jar包

  <!-- hutool工具包 --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.12</version></dependency><!--生成二维码依赖包--><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.3.3</version></dependency><!--xml解析--><dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6.1</version></dependency>

(1)获取access_token

    /*** 获取access_token** @return*/public String createAccessToken() {String url = "https://api.weixin.qq.com/cgi-bin/token";Map<String, Object> data = new HashMap<>();data.put("grant_type", "client_credential");data.put("appid", wxConfig.getAppid());data.put("secret", wxConfig.getSecret());log.info("createAccessToken data:{}", data);String json = HttpUtil.createGet(url).form(data).execute().body();String access_token = (String) JSONUtil.getByPath(JSONUtil.parse(json), "access_token");return access_token;}

(2)获取临时二维码

这里需要注意的是:

action_name:QR_SCENE(场景值ID,临时二维码时为32位非0整型,永久二维码时最大值为100000(目前参数只支持1--100000))

action_name:QR_STR_SCENE(场景值ID(字符串形式的ID),字符串类型,长度限制为1到64)

  /*** 创建临时二维码** @return*/public String createTempQrCode(String access_token, String scene_str) {String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + access_token;Map<String, Object> data = new HashMap<>();data.put("expire_seconds", 604800);data.put("action_name", "QR_STR_SCENE");Map<String, Object> action_info = new HashMap<>();Map<String, Object> scene = new HashMap<>();scene.put("scene_str", scene_str);action_info.put("scene", scene);data.put("action_info", action_info);String json = HttpUtil.createPost(url).header("Content-Type", "application/json").body(JSONUtil.toJsonStr(data)).execute().body();System.out.println("json = " + json);String qrcode = (String) JSONUtil.getByPath(JSONUtil.parse(json), "url");return qrcode;}

(3)微信推送事件方法

get请求接口主要用于签名验证。(在配置开发者服务器配置(已启用)时会用到)

post请求接口主要用于事件接收逻辑处理

/** @param signature 微信加密签名,signature结合了开发者填写的 token 参数和请求中的 timestamp 参数、nonce参数。* @param timestamp 时间戳* @param nonce     这是个随机数* @param echostr   随机字符串,验证成功后原样返回*/@GetMapping("/wx/event")public void get(@RequestParam(required = false) String signature,@RequestParam(required = false) String timestamp,@RequestParam(required = false) String nonce,@RequestParam(required = false) String echostr,HttpServletResponse response) throws IOException {response.setCharacterEncoding("UTF-8");response.getWriter().write(echostr);response.getWriter().flush();response.getWriter().close();}//处理微信推送事件@PostMapping("/wx/event")public void post(final HttpServletRequest request, HttpServletResponse response) {try {// 微信加密签名final String signature = request.getParameter("signature");// 时间戳final String timestamp = request.getParameter("timestamp");// 随机数final String nonce = request.getParameter("nonce");// 随机字符串final String echostr = request.getParameter("echostr");//将xml文件转成易处理的map(下方贴出)final Map<String, String> map = parseXml(request);//开发者微信号final String toUserName = map.get("ToUserName");//OpenIdfinal String fromUserName = map.get("FromUserName");//消息创建时间 (整型)final String createTime = map.get("CreateTime");//消息类型,eventfinal String msgType = map.get("MsgType");//事件类型final String event = map.get("Event");String scene_str = "";if ("event".equals(msgType)) {if (event.equals("subscribe")) {final String ticket = map.get("Ticket");if (ticket != null) {scene_str = map.get("EventKey").replace("qrscene_", "");}}//注:事件类型为SCAN即已关注else if (event.equals("SCAN")) {final String ticket = map.get("Ticket");if (ticket != null) {scene_str = map.get("EventKey");}}}// 如果scene_str 不为空代表用户已经扫描并且关注了公众号if (StringUtils.isNotEmpty(scene_str)) {// 将微信公众号用户ID缓存到redis中,标记用户已经扫码完成,执行登录逻辑。redisCache.setCacheObject(scene_str, fromUserName, LoginStatus.SEESIOIN_TIME, TimeUnit.SECONDS);}response.getWriter().write("");} catch (Exception e) {e.printStackTrace();}}

(4)request请求转换为Map方法

    //将xml文件转成易处理的mappublic static Map<String, String> parseXml(final HttpServletRequest request) throws Exception {final Map<String, String> map = new HashMap<String, String>();InputStream inputStream = request.getInputStream();final SAXReader reader = new SAXReader();final Document document = reader.read(inputStream);final Element root = document.getRootElement();final List<Element> elementList = (List<Element>) root.elements();for (final Element e : elementList) {map.put(e.getName(), e.getText());}inputStream.close();inputStream = null;return map;}

(5)检查微信登录状态

    /*** 检查微信登录状态** @return*/@PostMapping("/wxLogin")@ResponseBodypublic AjaxResult checkWxLoginStatus(HttpSession session) {String scene_str = (String) session.getAttribute("scene_str");if (StringUtils.isEmpty(scene_str)) {return AjaxResult.custom("二维码已过期", 1001);}String loginStatus = redisCache.getCacheObject(scene_str);if (LoginStatus.NOT_LOGIN.equals(loginStatus)) {return AjaxResult.custom("未登录", 1002);}//执行登录方法try {autoWxLogin(loginStatus);} catch (Exception e) {return AjaxResult.error(e.getMessage());}return AjaxResult.success("登录成功");}

五、你可能会遇到的问题

(1)填写服务配置可能会遇到的问题

 如果配置的url不能访问,会报token验证失败。在本地开发测试,可以借助于网穿透工具:Sunny-Ngrok内网转发内网穿透 - 国内内网映射服务器

(2)本地正常,服务器上无法调用

有可能你在本地开发过程中是没有问题,但是你将代码发布到服务器上的时候,发现接口调用失败。有可能是你没有将公网服务器IP添加到白名单导致的。

多个白名单配置方法:每行配置一个IP地址即可。

六、结语

本章教程到这里就结束了,以上内容仅来自于博主的自我总结,也许其中有总结不到为的地方,希望能您够多多理解,感谢你的阅读,希望对你有一点点的帮助。

相关文章:

基于微信公众号(服务号)实现扫码自动登录系统功能

微信提供了两种方法都可以实现扫描登录。 一种是基于微信公众平台的扫码登录&#xff0c;另一种是基于微信开放平台的扫码登录。 两者的区别: 微信开放平台需要企业认证才能注册&#xff08;认证费用300元&#xff0c;只需要认证1次&#xff0c;后续不再需要进行缴费年审&#…...

AXI实战(二)-跟着产品手册设计AXI-Lite外设(AXI-Lite转串口实现)

AXI实战(二)-跟着产品手册设计AXI-Lite 设(AXI-Lite转串口实现) 看完在本文后,你将可能拥有: 一个AXI_Lite转串口的从端(Slave)设计使用SV仿真AXI-Lite总线的完整体验实现如何在读通道中实现"等待"小何的AXI实战系列开更了,以下是初定的大纲安排: 欢迎感兴趣的…...

一周搞定模拟电路视频教程,拒绝讲PPT,仿真软件配合教学,真正一周搞定

目录1、灵魂拷问2、懦夫救星3、福利领取2、使用流程1、灵魂拷问 问&#xff1a;模拟电路很难吗&#xff1f; 答&#xff1a;嗯&#xff0c;真的很难&#xff01;&#xff01;&#xff01; 问&#xff1a;模拟电路容易学吗&#xff1f; 答&#xff1a;很难学&#xff0c;建议放…...

高德地图获得角度

//传入两个经纬度点得到车辆角度 设置车辆Marker角度 getAngle(startPoint, endPoint) {if (!(startPoint && endPoint)) {return 0;}let dRotateAngle Math.atan2(Math.abs(startPoint.lng - endPoint.lng),Math.abs(startPoint.lat - endPoint.lat));console.log(&q…...

【C++】-- C++11基础常用知识点(下)

上篇&#xff1a; 【C】-- C11基础常用知识点&#xff08;上&#xff09;_川入的博客-CSDN博客 目录 新的类功能 默认成员函数 可变参数模板 可变参数 可变参数模板 empalce lambda表达式 C98中的一个例子 lambda表达式 lambda表达式语法 捕获列表 lambda表达底层 …...

提到数字化,你想到哪些关键词

我们的生活中已经充满了数据&#xff0c;各种岗位例如运营、市场、营销上也都喜欢在职位要求加上一条利用数据、亦或是懂得数据分析。事实上&#xff0c;数据已经成为了构建现代社会的基本生产要素&#xff0c;并且因为不受自然环境的限制&#xff0c;已经成为了人们对未来社会…...

【蓝桥杯集训·每日一题】AcWing 1249. 亲戚

文章目录一、题目1、原题链接2、题目描述二、解题报告1、思路分析2、时间复杂度3、代码详解三、知识风暴并查集一、题目 1、原题链接 1249. 亲戚 2、题目描述 或许你并不知道&#xff0c;你的某个朋友是你的亲戚。 他可能是你的曾祖父的外公的女婿的外甥女的表姐的孙子。 如果…...

iphone所有机型的屏幕尺寸

手机设备型号屏幕尺寸(吋)分辨率点数(pt)屏幕显示模式分辨率像素(px)屏幕比例iPhone SE4.03205682x640113616:9iPhone 6/6s/7/8/SE 24.73756672x750133416:9iPhone 6P/7P/8P5.54147363x1242220816:9iPhone XR/116.14148962x828179219.5:9iPhone X/XS/11P5.83758123x1125243619.…...

Windows10使用-处理IE自动跳转至Edge

文章目录 前言一、调整Edge二、调整Internet选项三、搜索栏的恢复总结前言 微软官方宣布,自2023年2月14日永久停止支持Internet Explorer 11浏览器。后期点击IE 图标将会自动跳转到Edge界面。对于一些网站,可能需要使用IE模式才能正常使用,这时候就需要做相应的调整,才能够…...

linux input子系统,gpio-keys,gpio中断使用

GPIO控制 嵌入式linux下应用编程会经常使用到gpio&#xff0c;GPIO 可以通过 sysfs 方式进行操控&#xff0c;进入到/sys/class/gpio 目录下&#xff0c;如下所示&#xff1a; 可以看到该目录下包含两个文件 export、 unexport 以及 5 个 gpiochipX&#xff08;X 等于 0、 32、…...

分析称勒索攻击在非洲、中东与中国增长最快

Orange Cyberdefense&#xff08;OCD&#xff09;于 2022 年 12 月 1 日发布了最新的网络威胁年度报告。报告中指出&#xff0c;网络勒索仍然是头号威胁 &#xff0c;也逐渐泛滥到世界各地。 报告中的网络威胁指的是企业网络中的某些资产被包括勒索软件在内的攻击进行勒索&…...

ArcPy批量合并矢量shape文件

当有大量矢量&#xff08;.shp&#xff09;格式文件需要合并成一个矢量文件时&#xff0c;可以考虑使用 ArcPy 进行批量合并&#xff0c;代码如下&#xff1a; # coding:utf-8 import os import arcpy from arcpy import envenv.workspace "C:/Users/Desktop/demo"…...

改写有序表的题目核心点

1、核心点 1&#xff09;分析增加什么数据项可以支持题目 2&#xff09;有序表一定要保持内部参与排序的key不重复 【补充说明&#xff1a;要存储重复的key值&#xff0c;要么将相同的key压在一起&#xff0c;要么将每个key再封装一层&#xff0c;用内存地址区分】 3&#…...

收藏这几个开源管理系统做项目,领导看了直呼牛X!

项目SCUI Admin 中后台前端解决方案Vue .NetCore 前后端分离的快速发开框架next-admin 适配移动端、pc的后台模板django-vue-admin-pro 快速开发平台Admin.NET 通用管理平台RuoYi 若依权限管理系统Vue3.2 Element-Plus 后台管理框架Pig RABC权限管理系统zheng 分布式敏捷开发…...

【刷题篇】链表(下)

前言&#x1f338;各位读者们好&#xff0c;本期我们来填填之前留下的坑&#xff0c;继续来讲解几道和链表相关的OJ题。但和上期单向链表不一样的是&#xff0c;我们今天的题目主要是于环形链表有关&#xff0c;下面让我们一起看看吧。&#x1f4bb;本期的题目有&#xff1a;环…...

Shiro

Shiro 1.权限管理概述 2.Shiro权限框架   2.1 概念   2.2 Apache Shiro 与Spring Security区别 3.Shiro认证   3.1 基于ini认证   3.2 自定义Realm --认证 4.Shiro授权   4.1 基于ini授权   4.2 自定义realm – 授权 5.项目集成shiro 认证-授权注意点   5.1 认证…...

使用nginx进行负载均衡配置详细说明

使用nginx进行负载均衡 1. nginx负载均衡介绍 nginx应用场景之一就是负载均衡。在访问量较多的时候&#xff0c;可以通过负载均衡&#xff0c;将多个请求分摊到多台服务器上&#xff0c;相当于把一台服务器需要承担的负载量交给多台服务器处理&#xff0c;进而提高系统的吞吐…...

N皇后问题

#include<iostream> #include<string> #include<vector> using namespace std; #define MAX 20//最大20个皇后 int n ;//实际皇后个数 int sum ;//答案个数 vector<vector<int>> attack(MAX, vector<int>(MAX, 0));//标记攻击位置 vector&…...

强化学习DQN之俄罗斯方块

强化学习DQN之俄罗斯方块强化学习DQN之俄罗斯方块算法流程文件目录结构模型结构游戏环境训练代码测试代码结果展示强化学习DQN之俄罗斯方块 算法流程 本项目目的是训练一个基于深度强化学习的俄罗斯方块。具体来说&#xff0c;这个代码通过以下步骤实现训练&#xff1a; 首先…...

1.3总线:并行总线、串行总线、单工、半双工、全双工、总线宽度、总线带宽、总线的分类、数据总线、地址总线、控制总线

1.3总线&#xff1a;并行总线、串行总线、单工、半双工、全双工、总线宽度、总线带宽、总线的分类、数据总线、地址总线、控制总线总线并行总线、串行总线单工、半双工、全双工总线宽度总线带宽总线的分类数据总线&#xff08;Data Bus&#xff0c;DB&#xff09;地址总线&…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

label-studio的使用教程(导入本地路径)

文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

java 实现excel文件转pdf | 无水印 | 无限制

文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

Java - Mysql数据类型对应

Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...