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

微信公众号对接获取用户openid预约项目心路全历程

公众号对接获取openid全历程

    • 一、背景
    • 二、选型
    • 三、开始修改若依框架
    • 四、自己搭后端框架
    • 五、前端框架uni-app修改
    • 六、对接获取公众号登录用户openId
    • 七、总结

一、背景

老板接了朋友的一个公众号需求,要求做一个简单的疫苗预约系统。功能是获取当前登录用户,记录用户选择的疫苗,针次,时间,并且用户可以查看自己预约的记录。我刚接到这个需求感觉也简单,给的时间呢也只有一周,包括程序的开发,服务的部署,公众号相关信息的配置。虽然是个很小的功能,没想到期间碰到过很多坑,公众号也是我第一次全流程的做,记录一下这期间的坎坷。

二、选型

一般接到这种小功能的开发,我们一般会在开源框架市场找几个相似的项目然后修修改改,达到甲方想要的使用预期。前三天基本都是浪费在选型这一块了,本来也想着,选好开源项目,改起来也快,最后敲定选用若依uni-app这款,可没想到,最后改了半天,最后忍无可忍,自己手写了一套后端,前端代码,框架当然用的还是springboot+uni-app。。。

三、开始修改若依框架

若依这套框架也是典型的租户型框架,uniapp启动后是一个登录界面,而公众号要做默认登录,是不要这个登录界面的,那怎么跳过这个登录界面,直接登录进去呢,一开始想的是默认获取用户openid直接授权进去,这就要对应的修改后端生成token的方式,然后每一个页面访问的header还要携带这个token。

除此之外,登录进去后才展示的业务界面还需要画一下,那就先把页面画出来,一共做了四个页面,用户首页(展示预约疫苗入口和用户预约记录),用户信息维护(点击预约疫苗后先维护自己的信息,包括姓名,身份证号,手机号),预约界面(三个相互隐藏的栏位,疫苗栏位,针次栏位,时间栏位),疫苗说明界面。这里说一下微信公众号静默获取的信息只能获取到openId,unionid应该也可以获取,我没试过。获取openId的过程后面会说明。这里让用户自己维护手机号和身份证号是因为可能会给长辈预约疫苗。

页面画完之后,数据都是用的前端代码模拟的值,流程无碍之后,准备后端添加接口,业务表是甲方直接提供,使用的是sqlServer数据库,若依用的数据库版本是mysql,最后又找了一下,找到了若依sqlserver版本的后端框架,发现没法改,主要还是认证这一个部分,如果要改造认证这一部分,又要花费很多工作时间,改造过程中可能还会产生新的问题或者bug都是没法预估的,不是说若依不好用,只能说没必要用这种shiro认证框架,太冗余了。

四、自己搭后端框架

不需要认证,获取到当前登录用户的openID进行数据隔离和查询也可以保证数据的安全性。

  • 新建一个springboot项目

  • 删除多余的文件夹

  • 修改pom.xml的一些配置和添加我所需要的maven依赖,sqlSerer驱动,mybatisplus,springboot启动的依赖自带的,fastjson,druid数据池,多数据源,lombok,当然hutool也要

        <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><!-- 阿里JSON解析器 --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.75</version></dependency><!-- druid --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.4</version></dependency><!-- 动态数据源 --><dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>3.5.2</version></dependency><!-- SqlServer 数据库连接包 --><dependency><groupId>com.microsoft.sqlserver</groupId><artifactId>sqljdbc4</artifactId><version>4.0</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.1</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-core</artifactId><version>3.4.1</version></dependency><!-- Lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.18</version></dependency></dependencies>
    
  • 感觉又回到了刚学spring框架的那个时候了,做项目基本用开源框架或者公司自己的产品框架开发,很少自己搭spring项目了。

  • 然后修改pom.xml的打包配置选项

        <build><finalName>yuyue</finalName><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><includeSystemScope>true</includeSystemScope></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-dependency-plugin</artifactId><executions><execution><id>copy</id><phase>package</phase><goals><goal>copy-dependencies</goal></goals><configuration><outputDirectory>${project.build.directory}/lib</outputDirectory></configuration></execution></executions></plugin><!--指定JDK编译版本 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>2.3.2</version><configuration><source>1.8</source><target>1.8</target><encoding>UTF-8</encoding></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>3.1.2</version><configuration><skipTests>true</skipTests></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-resources-plugin</artifactId><configuration><nonFilteredFileExtensions><nonFilteredFileExtension>woff</nonFilteredFileExtension><nonFilteredFileExtension>woff2</nonFilteredFileExtension><nonFilteredFileExtension>eot</nonFilteredFileExtension><nonFilteredFileExtension>ttf</nonFilteredFileExtension><nonFilteredFileExtension>svg</nonFilteredFileExtension></nonFilteredFileExtensions></configuration><version>3.1.0</version></plugin></plugins><resources><resource><directory>src/main/resources</directory><filtering>true</filtering></resource><resource><directory>src/main/java</directory><includes><include>**/*.xml</include><include>**/*.json</include><include>**/*.ftl</include></includes></resource></resources></build>
    
  • 使用yaml配置文件,配置内容如下

    server:port: 8080servlet:context-path: /compression:enabled: truemin-response-size: 1024mime-types: application/javascript,application/json,application/xml,text/html,text/xml,text/plain,text/css,image/*spring:datasource:druid:stat-view-servlet:enabled: trueloginUsername: adminloginPassword: 123456allow:web-stat-filter:enabled: truedynamic:datasource:master:# 本地url: jdbc:sqlserver://localhost:1433;DatabaseName=Lanshanusername: sapassword: root# mybatis plus 设置
    mybatis-plus:mapper-locations: classpath*:com/yuyue/**/xml/*Mapper.xml#  configuration:#关闭二级缓存,默认开启#    cache-enabled: false#    log-impl: org.apache.ibatis.logging.stdout.StdOutImplglobal-config:# 关闭MP3.0自带的bannerbanner: falsedb-config:# 主键类型  0:"数据库ID自增",1:"该类型为未设置主键类型", 2:"用户输入ID",3:"全局唯一ID (数字类型唯一ID)", 4:"全局唯一ID UUID",5:"字符串全局唯一ID (idWorker 的字符串表示)";id-type: 4# 默认数据库表下划线命名table-underline: true# 配置逻辑删除logic-delete-field: deletedlogic-delete-value: 1logic-not-delete-value: 0#  这个配置会将执行的sql打印出来,在开发或测试的时候可以用configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImplconfiguration-properties:# 配置流程引擎参数,详情可见 DatabaseConfigurationblobType: BLOBboolValue: TRUE# 不要设置库名,否则会出现双库名 bugprefix: ''
    # Mybatis输出sql日志
    logging:level:com.yuyue: debug
    
  • 然后就写相关的实体类,mapper,service,controller。

  • 写完到这里就基本没问题了,可以正常启动。

五、前端框架uni-app修改

前端框架虽然没有从0开始做,还是用的若依的uniapp,但是做了其他额外的工作量,打开首页的页面修改成我的首页,我所新加的页面都要在permission.js中排除掉,要不然会重定向到首页。去掉若依下面的固定栏位。剩下的就是添加接口js文件,然后在页面中将数据的获取方式从模拟值修改为访问后端接口返回。

这些都还是比较简单,过程有点繁琐而已,当前面都改完之后,这个项目最大的难点来了,就是openid的获取。根据微信官方文档所写,获取openid分为两部分,根据appid获取到微信返回回来的code,然后根据code和appid和app密钥获取该用户的openId。需要公众号提供的参数如下:

  • appId
  • app密钥secret

以下介绍对接获取微信公众号登录用户openId的过程

六、对接获取公众号登录用户openId

前提:以上程序开发完成并且配置到服务里面,服务证书访问并申请开启域名访问。

首先需要公众号进行如下的一些配置和操作

  • 配置网页授权域名
    在这里插入图片描述 配置网页授权域名的时候,保存的时候微信会校验一个文件,如下图
    在这里插入图片描述

    下载上图提到的文件,开启域名后需要同步开启80端口访问,然后将文件上传到服务器80端口的根目录,如果不知道根目录位置,可以找一下nginx或者网站的配置项。域名填写的内容如下示例:www.xxx.com,不用加前缀,不用加端口号。然后点击保存,如果提示域名活路径格式不正确说明你上传的文件放错位置了,文件放上去之后,确保访问www.xxx.com/上传文件名可以访问到。

  • 公众号添加IP访问白名单
    在这里插入图片描述

    将服务器的外网ip填写进去即可。

  • 提供公众号的appid和secret

  • 绑定微信公众号的开发者微信号

    作为开发人员,如果不绑定这个东西就属于是隧洞摸黑前行,永远也想不到有多少个坑在等你。
    在这里插入图片描述

    需要开发人员先关注该公众号,然后将你的微信号提供出来,在公众号中进行开发者绑定。

以上,公众号的配置暂告一段落。

接下来,程序开始修改获取openId。

程序修改后,如何验证正确性以及中间过程访问的参数是否正确,这个时候我们需要用到微信开发者工具

在这里插入图片描述

打开这个软件,然后用绑定公众号开发者的微信号登录,访问服务器部署的url,就能看到调用的接口了(做这种对接就不要想着本地调试了)。唯一麻烦的只有每次修改完代码后,需要将代码打包放在服务器然后解压。

  • 根据appId获取微信返回回来的CODE

    访问url:https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

    需要修改的参数是:APPID,REDIRECT_URI

    APPID就是以上公众号提供出来的appId,REDIRECT_URI是重定向结果的url,这个重定向是微信官方那边做的,我们不用管如何重定向,需要注意的是重定向的url需要使用javaScript函数encodeURIComponent()进行编码

    示例:

    redirectToAuth() {const redirectUri = encodeURIComponent('https://www.xxx.cn')const authUrl = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid='+this.appid+'&redirect_uri='+redirectUri+'&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect'window.location.href = authUrl;}// 访问后页面会刷新重定向为
    // https://www.xxx.cn?CODE=xxxxxxxxx
    
  • 处理微信返回来的CODE

    接下来要根据CODE和appid和secret获取到用户的openid,记住,这个过程一定要在后端完成,不可在前端代码完成,这个地方有坑,差点被坑哭了(>_<)。使用前端返回openid,接口会提示跨域异常,没有返回数据。

    首先获取url中的CODE参数

    const code = (new URLSearchParams(window.location.search)).get('code')
    

    接下来发起后端调用,我这里使用hutool的http工具访问,如下示例

    访问url:https://api.weixin.qq.com/sns/oauth2/access_token

    String resultOpen = HttpUtil.get("https://api.weixin.qq.com/sns/oauth2/access_token?" +"appid=" + appid +//公众号ID"&secret=" + secret//公众号密钥"&code=" + code + //前端 传入 code"&grant_type=authorization_code");
    JSONObject jsonObject = JSONObject.parseObject(resultOpen);
    if (jsonObject.containsKey("errcode")) {String s = codeMap.get(code);if(StrUtil.isBlank(s)) {return Result.error(resultOpen);}else{return Result.ok(s);}
    }
    openId = jsonObject.get("openid").toString();
    

    正常返回的参数如下

    {"access_token":"ACCESS_TOKEN","expires_in":7200,"refresh_token":"REFRESH_TOKEN","openid":"OPENID","scope":"SCOPE","is_snapshotuser": 1,"unionid": "UNIONID"
    }
    

    错误返回的参数如下

    {"errcode":40029,"errmsg":"invalid code"}
    
  • 当我们正确拿到这个openid就可以为所欲为了(不是),就可以正常进行后续的业务操作了。

  • 最后让客户将我们项目的访问链接配置在公众号的菜单就可以啦

七、总结

真正开发的时间其实是从周五下午开始,期间我还在忙另一个正在上线的项目。这个功能虽然要求不多,但是涉及到对接,期间的坑属实不少,看着网上一篇有一篇的攻略,却总是抓不住要点,就openid要后端才能获取这个,很多网上教程说直接用前端代码获取,可能之前可以,但是现在不行了。客户下周一验收此功能,可以算得上3天搞定一个公众号对接案例,涉及到对接微信的东西不多,只有一个获取用户openid,这一个小东西就能碰到很多坑。

经过这次项目,可以看得出制定方案选型有多么重要,真正干活其实方向对了很快就出活了,如果方向不对,比如这次公众号开发就是要改造若依框架,可能2周都出不来。

相关文章:

微信公众号对接获取用户openid预约项目心路全历程

公众号对接获取openid全历程 一、背景二、选型三、开始修改若依框架四、自己搭后端框架五、前端框架uni-app修改六、对接获取公众号登录用户openId七、总结 一、背景 老板接了朋友的一个公众号需求&#xff0c;要求做一个简单的疫苗预约系统。功能是获取当前登录用户&#xff0…...

大中小协作 共筑科学梦——华中科技大学附属花城中学举办首届科技节

为普及科学知识&#xff0c;张扬科学精神&#xff0c;创设浓郁的科学氛围&#xff0c;11月24日&#xff0c;华中科技大学附属花城中学举办了以“走近科学&#xff0c;触碰未来”为主题的首届科技节暨科创文化展示周活动。学生们在学习中感受科技的魅力&#xff0c;在“玩”中感…...

ElasticSearch之Health API

查看当前集群全部健康指标的信息&#xff0c;执行如下命令&#xff1a; curl -X GET "https://localhost:9200/_health_report?pretty" --cacert $ES_HOME/config/certs/http_ca.crt -u "elastic:ohCxPHQBEs5*lo7F9"执行结果输出如下&#xff1a; {&quo…...

图的建立基本操作

#include <stdio.h> #include <stdlib.h> #include <stdbool.h> // 添加头文件#define MAX_VERTEX_NUM 100 //图中最大顶点数//struct ArcNode* nextarc; //ArcNode* firstarc; //这两个是很有必要的&#xff0c;如果你没有这两个指针&#xff0c;你就无法判…...

影响语音芯片识别率的因素概述

语音芯片识别率是指芯片对人类语音信号的识别能力。在实际应用中&#xff0c;语音芯片识别率的高低直接影响了用户对芯片的体验和满意度。因此&#xff0c;提高语音芯片识别率是当前语音技术领域的重要任务之一。 1.、语音芯片的硬件设计&#xff1a;设计良好的芯片可以更好地…...

操作系统的主要功能--处理机、存储器、设备、文件

一、处理机管理功能 对处理机的管理可以归结为对进程的管理。处理机管理的主要功能包括&#xff1a;创建和撤销进程&#xff0c;对进程的运行进行协调&#xff0c;实现进程之间的信息交换&#xff0c;并且按照异地你给的算法将处理机分配给进程 进程控制&#xff1a;为一个作…...

PDF 批量处理软件BatchOutput PDF mac中文版介绍

BatchOutput PDF mac是一款适用于 Mac 的 PDF 批量处理软件。它可以帮助用户将多个 PDF 文件进行异步处理&#xff0c;提高工作效率。 BatchOutput PDF 可以自动化执行许多任务&#xff0c;包括 PDF 文件的打印、转换、分割、压缩、加密、重命名等&#xff0c;而且它还可以将自…...

oracle安装的肘腋之疾小合集

#临时空间指定 export TMP/tmp export TMPDIR/tmp #图形化显示框不全 java问题&#xff0c;使用系统自带的jre ./runInstaller -jreLoc/usr/local/jdk1.7.0_80/ #ins30131 Failed to access the temporary location 给/tmp/CVU*加x权限 #linux桌面太小 xrandr -s 1440x900_60…...

django(千锋教育)

创建一个django项目 官网下载python最新版本 配置到环境变量中 打开intlij编辑器 创建django项目 安装django&#xff1a;pip install django 创建django项目: django-admin startproject django01 创建djangoAPP&#xff1a;python manage.py startapp user 启动&#xff1…...

Python 前后端分离项目Vue部署应用

一、视图创建 from django.http import JsonResponse from django.shortcuts import render# Create your views here. from django.views import Viewclass IndexView(View):def get(self,request):# 前后端分离 &#xff08;前端JS代码渲染数据&#xff09;return JsonRespo…...

Linux中安装MySQ-合集

Linux中安装MySQL Centos中 1、卸载不必要的软件 先卸载mariadb安装MySQL必要环境 rpm -qa|grep mariadb rpm -e --nodeps mariadb-libs yum install -y gcc-c yum install net-tools yum -y install gcc如果需要Java等程序 yum install -y java* java-1.8.0-openjdk* op…...

elk 简单操作手册

1.1. 基础概念 EFK不是一个软件,而是一套解决方案,开源软件之间的互相配合使用,高效的满足了很多场合的应用,是目前主流的一种日志系统。 EFK是三个开源软件的缩写,分别表示:Elasticsearch , Filebeat, Kibana , 其中Elasticsearch负责日志保存和搜索,Filebeat负责收集日志,Ki…...

CSS画一条线

<p style"border: 1px solid rgba(0, 0, 0, 0.1);"></p> 效果&#xff1a;...

分享常用设计模式之单例模式(懒汉模式和饿汉模式)和几种关于设计模式的面试题

目录 1.单例模式 1.懒汉模式 2.饿汉模式 2.设计一个不能被继承的类 3.设计一个不能被继承但是可以在外部环境创建该类对象的类 4.设计一个可以被继承但不能在外部环境创建该类的对象的类 5.限制派生类对象不能拷贝也不能赋值 1.单例模式 设计一个不能在外部环境创建该类…...

python每日一题——6三数之和

题目 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的三元组。 …...

黑马点评笔记 分布式锁

文章目录 分布式锁基本原理和实现方式对比Redis分布式锁的实现核心思路实现分布式锁版本一Redis分布式锁误删情况说明解决Redis分布式锁误删问题分布式锁的原子性问题分布式锁-Redission分布式锁-redission可重入锁原理分布式锁-redission锁重试和WatchDog机制分布式锁-redissi…...

java---抽象类 用abstract修饰

抽象类是不能被[ 直接 ] [ 显式 ]实例化的如果抽象类中有一个抽象方法,那么这个类一定要声明为抽象类(反过来说,如果一个类是抽象类,那么它里面可以没有抽象方法)如果父类中有一个抽象方法,那么抽象的子类,要么也得是抽象的,要么就把抽象的方法全部给具体化(实现了) 抽象方法 …...

JVM 之 javac、java、javap 命令详解

目录 一. 前言 二. javac 命令 三. java 命令 四. javap 命令 一. 前言 在日常工作中&#xff0c;我们新建 Java工程&#xff0c;写好代码后&#xff0c;编译和运行几乎都是通过 IDE&#xff08;如idea、eclipse&#xff09;工具完成。但作为 Java开发者还是要了解下 Java虚…...

市场被套牢,没有了解积累和分配,昂首资本一一介绍

很多投资者对市场中的积累和分配的概念不是很清楚&#xff0c;下面昂首资本将一一介绍。 积累意味着尽可能多地买入筹码&#xff0c;而不大幅抬高价格&#xff0c;直到在你买入时的价格水平上没有或几乎没有筹码。这种买入通常发生在市场熊市之后&#xff0c;此时有最佳买入价…...

notion 3.0.0 版本最新桌面端汉化教程,支持MAC和WIN版本

notion客户端汉化&#xff08;目前版本3.0.0&#xff09; 最近notion桌面端更新了3.0.0版本后会导致老版本汉化失效&#xff0c;本项目实现了最新版Notion桌面端的汉化。 文件下载地址&#xff1a;汉化文件下载地址 项目说明 本项目针对新的客户端做了汉化文化&#xff0c;依…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器

拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件&#xff1a; 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...

字符串哈希+KMP

P10468 兔子与兔子 #include<bits/stdc.h> using namespace std; typedef unsigned long long ull; const int N 1000010; ull a[N], pw[N]; int n; ull gethash(int l, int r){return a[r] - a[l - 1] * pw[r - l 1]; } signed main(){ios::sync_with_stdio(false), …...