【SpringBoot】-- 项目实现微信公众号扫码登录

目录

一、业务需求

二、内网穿透

三、服务器配置

​编辑

四、依赖引入

pom.xml

五、验证服务器有效性

代码

controller类

SHA1工具类

六、用户订阅后自动回复消息

代码

controller类

 MessageUtil工具类

七、用户发送文本消息后回复消息

代码

controller类

八、拓展


一、业务需求

手机扫描二维码后关注公众号,发送验证码给公众号,公众号返回验证码,然后输入到网页判断验证码是否正确后通过登录。

二、内网穿透

内网穿透是,它允许通过公共网络(比如互联网)将数据传输到内部网络中,即使内部网络处于防火墙或NAT(网络地址转换)等保护措施之后也能实现。这对于需要从外部访问内部网络资源的场景非常有用,使用场景是外部网络访问内部网络的情况,比如远程访问家庭网络中的设备。

这里使用的内网穿透工具是natapp

内网穿透使用指南:

NATAPP1分钟快速新手图文教程 - NATAPP-内网穿透 基于ngrok的国内高速内网映射工具

输入命令启动:start natapp -authtoken=xxxx

启动后会有一个地址

三、服务器配置

测试号地址:微信公众平台

这里的Token暂可随便输入

四、依赖引入

pom.xml

  <properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.version>2.4.2</spring-boot.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><artifactId>spring-boot-starter-logging</artifactId><groupId>org.springframework.boot</groupId></exclusion></exclusions></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.16</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId></dependency><!-- json处理--><dependency><groupId>com.thoughtworks.xstream</groupId><artifactId>xstream</artifactId><version>1.4.18</version></dependency><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.8.5</version></dependency><dependency><groupId>org.dom4j</groupId><artifactId>dom4j</artifactId><version>2.1.1</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.12.7</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.12.7</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId><version>2.9.0</version></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><repositories><repository><id>central</id><name>aliyun maven</name><url>http://maven.aliyun.com/nexus/content/groups/public/</url><layout>default</layout><releases><enabled>true</enabled></releases><snapshots><enabled>true</enabled></snapshots></repository></repositories><build><finalName>${project.artifactId}</finalName><!--打包成jar包时的名字--><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>2.3.0.RELEASE</version><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins></build>

五、验证服务器有效性

开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,GET请求携带参数如下表所示:

参数

描述

signature

微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。

timestamp

时间戳

nonce

随机数

echostr

随机字符串

开发者通过检验signature对请求进行校验(下面有校验方式)。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,成为开发者成功,否则接入失败。加密/校验流程如下:

1)将token、timestamp、nonce三个参数进行字典序排序

2)将三个参数字符串拼接成一个字符串进行sha1加密

3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信

代码

controller类

这里的token需要和上面服务器配置的token一致

    private static final String token = "aeaae";/*** 回调消息校验*/@GetMapping("callback")public String callback(@RequestParam("signature") String signature,@RequestParam("timestamp") String timestamp,@RequestParam("nonce") String nonce,@RequestParam("echostr") String echostr){log.info("get验签请求参数:signature:{},timestamp:{},nonce:{},echostr:{}",signature,timestamp,nonce,echostr);String shaStr = SHA1.getSHA1(token,timestamp,nonce,"");if(signature.equals(shaStr)){return echostr;}return "unknown";}

SHA1工具类

/*** sha1生成签名工具*/
@Slf4j
public class SHA1 {/*** 用SHA1算法生成安全签名** @param token     票据* @param timestamp 时间戳* @param nonce     随机字符串* @param encrypt   密文* @return 安全签名*/public static String getSHA1(String token, String timestamp, String nonce, String encrypt) {try {String[] array = new String[]{token, timestamp, nonce, encrypt};StringBuffer sb = new StringBuffer();// 字符串排序Arrays.sort(array);for (int i = 0; i < 4; i++) {sb.append(array[i]);}String str = sb.toString();// SHA1签名生成MessageDigest md = MessageDigest.getInstance("SHA-1");md.update(str.getBytes());byte[] digest = md.digest();StringBuffer hexStr = new StringBuffer();String shaHex = "";for (int i = 0; i < digest.length; i++) {shaHex = Integer.toHexString(digest[i] & 0xFF);if (shaHex.length() < 2) {hexStr.append(0);}hexStr.append(shaHex);}return hexStr.toString();} catch (Exception e) {log.error("sha加密生成签名失败:", e);return null;}}
}

六、用户订阅后自动回复消息

用户在关注与取消关注公众号时,微信会把这个事件推送到开发者填写的URL。方便开发者给用户下发欢迎消息或者做账号的解绑。为保护用户数据隐私,开发者收到用户取消关注事件时需要删除该用户的所有信息。

<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[FromUser]]></FromUserName><CreateTime>123456789</CreateTime><MsgType><![CDATA[event]]></MsgType><Event><![CDATA[subscribe]]></Event>
</xml>

参数

描述

ToUserName

开发者微信号

FromUserName

发送方账号(一个OpenID)

CreateTime

消息创建时间 (整型)

MsgType

消息类型,event

Event

事件类型,subscribe(订阅)、unsubscribe(取消订阅)

代码

controller类

 @PostMapping(value = "callback",produces = "application/xml;charset=UTF-8")public String callback( @RequestBody String requestBody,@RequestParam("signature") String signature,@RequestParam("timestamp") String timestamp,@RequestParam("nonce") String nonce,@RequestParam(value = "msg_signature", required = false) String msgSignature){//解析微信发来的xmlMap<String,String> messageMap = MessageUtil.parseXml(requestBody);//获取事件类型和消息类型String msgType = messageMap.get("MsgType");String event = messageMap.get("Event") == null ? "" : messageMap.get("Event");//拼接StringBuilder sb = new StringBuilder();sb.append(msgType);if(!StringUtils.isEmpty(event)){sb.append(".");sb.append(event);}String msgTypeKey = sb.toString();//用户关注事件if(msgTypeKey.equals("event.subscribe")){return dealMsg(messageMap);}//用户发送文本消息else if(msgTypeKey.equals("text")){return dealUserMsg(messageMap);}return "unknown";}//用户关注事件public String dealMsg(Map<String,String> messageMap){String fromUserName = messageMap.get("FromUserName");String toUserName = messageMap.get("ToUserName");String subscribeContent = "感谢您的关注,我是四月天行健";String content = "<xml>\n" +"  <ToUserName><![CDATA[" + fromUserName + "]]></ToUserName>\n" +"  <FromUserName><![CDATA[" + toUserName + "]]></FromUserName>\n" +"  <CreateTime>12345678</CreateTime>\n" +"  <MsgType><![CDATA[text]]></MsgType>\n" +"  <Content><![CDATA[" + subscribeContent + "]]></Content>\n" +"</xml>";return content;}

 MessageUtil工具类

public class MessageUtil {/*** 解析微信发来的请求(XML).** @param msg 消息* @return map*/public static Map<String, String> parseXml(final String msg) {// 将解析结果存储在HashMap中Map<String, String> map = new HashMap<String, String>();// 从request中取得输入流try (InputStream inputStream = new ByteArrayInputStream(msg.getBytes(StandardCharsets.UTF_8.name()))) {// 读取输入流SAXReader reader = new SAXReader();Document document = reader.read(inputStream);// 得到xml根元素Element root = document.getRootElement();// 得到根元素的所有子节点List<Element> elementList = root.elements();// 遍历所有子节点for (Element e : elementList) {map.put(e.getName(), e.getText());}} catch (Exception e) {e.printStackTrace();}return map;}}

七、用户发送文本消息后回复消息

当用户发送消息给公众号时(或某些特定的用户操作引发的事件推送时),会产生一个POST请求,开发者可以在响应包(Get)中返回特定XML结构,来对该消息进行响应(现支持回复文本、图片、图文、语音、视频、音乐)。严格来说,发送被动响应消息其实并不是一种接口,而是对微信服务器发过来消息的一次回复。

<xml><ToUserName><![CDATA[toUser]]></ToUserName><FromUserName><![CDATA[fromUser]]></FromUserName><CreateTime>12345678</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[你好]]></Content>
</xml>

参数

是否必须

描述

ToUserName

接收方账号(收到的OpenID)

FromUserName

开发者微信号

CreateTime

消息创建时间 (整型)

MsgType

消息类型,文本为text

Content

回复的消息内容(换行:在content中能够换行,微信客户端就支持换行显示)

代码

controller类

    //用户发送文本事件public String dealUserMsg(Map<String,String> messageMap){String content = messageMap.get("Content");if (!"验证码".equals(content)) {return "";}String fromUserName = messageMap.get("FromUserName");String toUserName = messageMap.get("ToUserName");Random random = new Random();int num = random.nextInt(1000);String numContent = "您当前的验证码是:" + num + "! 5分钟内有效";String replyContent = "<xml>\n" +"  <ToUserName><![CDATA[" + fromUserName + "]]></ToUserName>\n" +"  <FromUserName><![CDATA[" + toUserName + "]]></FromUserName>\n" +"  <CreateTime>12345678</CreateTime>\n" +"  <MsgType><![CDATA[text]]></MsgType>\n" +"  <Content><![CDATA[" + numContent + "]]></Content>\n" +"</xml>";return replyContent;}

八、拓展

可以将验证码和微信返回的openid存储到redis中,然后在需要时可以从redis中取出数据,完成登录。

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

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

相关文章

基于SpringBoot+Vue的工厂生产设备维护管理系统(源码+文档+部署+讲解)

一.系统概述 随着社会的发展&#xff0c;系统的管理形势越来越严峻。越来越多的用户利用互联网获得信息&#xff0c;但各种信息鱼龙混杂&#xff0c;信息真假难以辨别。为了方便用户更好的获得工厂生产设备维护信息&#xff0c;因此&#xff0c;设计一种安全高效的工厂生产设备…

示波器接上机器板子信号就正常工作,拿下来就机器不正常工作

系列文章目录 1.元件基础 2.电路设计 3.PCB设计 4.元件焊接 5.板子调试 6.程序设计 7.算法学习 8.编写exe 9.检测标准 10.项目举例 11.职业规划 送给大学毕业后找不到奋斗方向的你&#xff08;每周不定时更新&#xff09; 【牛客网】构建从学习到职业的良性生态圈 中国计算…

Windows系统安装WinSCP结合内网穿透实现公网远程SSH本地服务器

List item 文章目录 1. 简介2. 软件下载安装&#xff1a;3. SSH链接服务器4. WinSCP使用公网TCP地址链接本地服务器5. WinSCP使用固定公网TCP地址访问服务器 1. 简介 ​ Winscp是一个支持SSH(Secure SHell)的可视化SCP(Secure Copy)文件传输软件&#xff0c;它的主要功能是在本…

一文读懂RISC-V与ARM

RISC-V和ARM是近年来备受关注的两种处理器架构。RISC-V是一种基于精简指令集计算(RISC)原理的开源指令集架构(ISA)&#xff0c;而ARM是一种专有ISA&#xff0c;由于其长期存在于嵌入式系统和移动设备中&#xff0c;已成为嵌入式系统和移动设备的主导选择。市场以及多年积累的信…

前端开发攻略---利用Flexbox和Margin实现智能布局:如何巧妙分配剩余空间,让你的网页设计更上一层楼?

1、演示 2、flex布局 Flex布局是一种用于Web开发的弹性盒子布局模型&#xff0c;它可以让容器内的子元素在空间分配、对齐和排列方面具有更大的灵活性。以下是Flex布局的基本用法&#xff1a; 容器属性&#xff1a; display: flex;&#xff1a;将容器指定为Flex布局。flex-dire…

Realme GT Neo6 SE ROOT 解锁BL教程

Realme GTNeo6 SE 解锁ROOT教程 前言&#xff1a; 本文解锁BL教程以及深度测试APP来自Realme官方社区。相关操作流程已进行简化&#xff0c;工具由本人制作并提供&#xff0c;降低上手难度&#xff0c;傻瓜式操作&#xff08;工具长期免费更新&#xff09;。 正文&#xff1a…

Python docx:在Python中创建和操作Word文档

使用docx库&#xff0c;可以执行各种任务 创建新文档&#xff1a;可以使用库从头开始或基于模板生成新的Word文档。这对于自动生成报告、信函和其他类型的文档非常有用。修改现有文档&#xff1a;可以打开现有的Word文档&#xff0c;并使用库修改其内容、格式、样式等。这对于…

2024高交会-2024深圳高新技术展-高新技术成果交易会

2024高交会-2024深圳高新技术展-2024高新技术成果展-中国高校技术交易会-第26届高交会-深圳高交会-深圳高科技展-深圳新科技展-深圳高新技术成果展 第二十六届中国国际高新技术成果交易会&#xff08;简称高交会&#xff09; 时间&#xff1a;2024年11月15日-19日 地址&#…

python+Flask+django企业仓库进销存管理信息系统35wiz

Flask提供了更大的灵活性和简单性&#xff0c;适合小型项目和微服务。Django则提供了更多的内置功能&#xff0c;适合大型项目。Flask让开发者更多的控制其组件&#xff0c;而Django则遵循开箱即用的原则 本课题使用Python语言进行开发。代码层面的操作主要在PyCharm中进行&am…

YOLOv8 推理脚本--置信度保留多位浮点数 特征图可视化

效果 特征图可视化: 4位浮点数: 原始2位浮点数4位浮点数推理 --detect.py 说明 在进行改动前,请大家先阅读下 基础入门篇 | YOLOv8 项目【训练】【验证】【推理】最简单教程 | YOLOv8必看 | 最新更新,直接打印 FPS,mAP50,75,95 ,确保会用我给的推理脚本。 YOLO( ):…

【C++】STL--stackquene

这一节主要学习stack、quene和priority_quene的使用以及模拟实现&#xff0c;最后介绍了容器适配器。 目录 stack的介绍和使用 stack的介绍 stack的使用 stack的模拟实现 queue的介绍和使用 queue的介绍 queue的使用 queue的模拟实现 priority_queue的介绍和使用 pri…

【漏洞复现】潍微科技-水务信息管理平台 ChangePwd SQL注入漏洞

0x01 产品简介 潍微科技-水务信息管理平台主要帮助水务企业实现水质状态监测、管网运行监控、水厂安全保障、用水实时监控以及排放有效监管,确保居民安全稳定用水、环境有效保护,全面提升水务管理效率。 0x02 漏洞概述 潍微科技-水务信息管理平台 ChangePwd 接口存在SQL注…

训练营第二十天(二叉树 part06)

训练营第二十天&#xff08;二叉树 part06&#xff09; 654.最大二叉树 力扣题目地址(opens new window) 题目 给定一个不含重复元素的整数数组。一个以此数组构建的最大二叉树定义如下&#xff1a; 二叉树的根是数组中的最大元素。左子树是通过数组中最大值左边部分构造出…

sed 字符替换时目标内容包含 特殊字符怎么处理

背景 想写一个自动修改配置的脚本&#xff0c;输入一个 mysql jdbc 的连接路径&#xff0c;然后替换目标配置中的模版内容&#xff0c;明明很简单的一个内容&#xff0c;结果卡在了 & 这个符号上。 & 到底是什么特殊字符呢&#xff1f;结论&#xff1a;它代表要替换的…

【中级软件设计师】上午题08-UML(上):类图、对象图、用例图

上午题08-UML 1 UML事物2 UML关系2.1 依赖2.2 关联2.2.1 聚合 &#xff08;空心菱形&#xff09;2.2.2 组合 &#xff08;实心菱形&#xff09; 2.3 泛化 &#xff08;实线三角形&#xff09;2.4 实现 &#xff08;虚线三角形&#xff09;2.5 关联多重度 3 类图4 对象图5 用例图…

vue3 + potree 渲染点云数据记录

potree 官网示例 前置条件&#xff1a; potree 无法直接加载 LAS&#xff0c;LCD&#xff0c;PLY等格式的点云文件, 需要通过 PotreeConverte 转换为 octree 数据格式&#xff0c;前端渲染中加载转换后的 json 格式 格式转换方向 .las ---- potreeConverter ----> .json…

算法练习第15天|226.翻转二叉树

226.翻转二叉树 力扣链接https://leetcode.cn/problems/invert-binary-tree/description/ 题目描述&#xff1a; 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&am…

关于无人机,你必须知道的事!!(科技篇)

飞行器的五脏六腑 电机&#xff1a;无人机的动力单元&#xff0c;俗称“马达”。通过电机转动来驱动螺旋桨旋转&#xff0c;最终让飞机上天。 电调&#xff1a;无人机的动力单元&#xff0c;是接收油门信号并调整电机转速的控制枢纽&#xff0c;俗称电机的“黑屋调教师” 飞…

探索计算机的小数世界:从二进制到无限精度

前言 不知道你是否和我一样&#xff0c;遇到这个情况。在刚开始学习编程。计算0.3-0.20.1这个小学都知道&#xff0c;但是如果你在计算机执行&#xff0c;发现结果并不是0.1 。这个时候会疑问到底是为什么呢。 System.out.println("0.3-0.2"(0.3-0.2)); 0.3-0.20.09…

API管理平台:你用的到底是哪个?

Apifox是不开源的&#xff0c;在github的项目只是readme文件&#xff0c;私有化需要付费。当然saas版目前是免费使用的。 一、Swagger 为了让Swagger界面更加美观&#xff0c;有一些项目可以帮助你实现这一目标。以下是一些流行的项目&#xff0c;它们提供了增强的UI和额外的功…