首页 > 其他分享 >一扫即入,如何通过微信公众号扫码登录网站?

一扫即入,如何通过微信公众号扫码登录网站?

时间:2024-04-07 09:47:22浏览次数:27  
标签:扫码 weixin 微信 二维码 即入 com 服务端

本文收录于 Github.com/niumoo/JavaNotes,Java 系列文档,数据结构与算法!
本文收录于网站:https://www.wdbyte.com/,我的公众号:程序猿阿朗

引言

想象一下,周五晚上,你打开电脑,打算刷一刷最新上线的剧集,突然弹出网站登录,哎呀,那个超级复杂的密码是什么来着?那一堆数字、字母和符号的大杂烩在我脑海中有好几个版本?能不能有一种简单的方式,不用密码就可以认真登录,这简直不要太棒?这时扫码登录出现了,它不仅方便而且更加安全。好比你向安保亮了一下你的 VIP 通行证,便放你通过。

微信作为国民级应用,微信扫码登录再常见不过了,它就像你的口袋里的万能钥匙,去哪儿都不怕。不过微信扫码登录也有多种方式,如扫码授权登录,扫码关注公众号登录等。这篇文章一起聊聊微信公众号二维码登录是怎么回事,它的工作流程是什么,它怎么保证你的身份安全。以及,如果你是一个开发者,如何在自己的网站上增加扫码登录。

公众号扫码登录优势

快捷方便

用户只需打开微信扫一扫,几秒钟内就能完成登录。这简化了传统的输入用户名和密码的繁琐过程,不过前提是你已经安装了必要的 APP。

增强安全性

扫码登录的身份认证在服务端完成,而且如微信公众号扫码登录这种方式,网站只需要拿到一个用户身份标识用于识别用户,不需要存储用户的额外信息。非常安全。

提升用户粘性

通过扫描二维码登录把用户引入公众号关注,在登录的同时还可以为公众号引流,提升用户粘性,同时公众号是一个非常方便的用户触达方式,未来新功能的发布可以及时送达用户。

公众号扫码登录实现原理

要想理清公众号扫码登录的实现原理,首先要知道在扫码登录过程中,有哪些参与方,它们之间的工作流程是怎么样的。这里的参与方有用户、浏览器、网站服务端、微信服务端四个参与方,总体的工作流程如下图,下面会进行详细介绍。

用户:用户是扫码登录的发起方,点击登录,然后扫描登录二维码。

浏览器:浏览器为用户展示二维码,然后不断的轮询扫码状态。

服务端:网站服务端需要向微信服务端获取携带 Ticket 信息的公众号二维码,在微信服务端回调时绑定用户身份信息。

微信服务端:用户扫码后,会请求到微信服务端,微信服务端会携带扫描的二维码的 Ticket 和用户身份标识回调网站服务端。

微信服务端回调网站服务端时,携带的用户身份信息其实只是一串无意义字符串,但是微信可以保证的是同一个微信用户扫码时携带的身份信息字符是相同的,以此识别用户。也因此公众号扫码登录用作身份认证非常安全。

开发准备工作

公众号

首先你要有用于扫码登录的微信公众号,微信公众平台提供了测试平台,可以直接生成测试公众号。

微信测试号:https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index

开发者文档

获取公众号二维码的过程需要参考微信公众号官方文档,下面几篇内容需要重点关注。

  1. 公众号接口接入指南

    链接:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html

  2. 获取 Access Token

    Access Token 是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用 Access Token 。每次获取有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的 Access Token 失效。

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

  3. 生成带 Ticket 二维码

    使用该接口可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送。

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

  4. 接收事件推送

    在用户扫码后微信服务端会回调网站服务端,开发者需要按照指定消息格式对消息进行验证处理。如获取二维码的 Ticket。

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

  5. 回复文本消息

    如果想要在用户扫码完成后自动响应如 “登录成功” 之类的提示语,需要参考此文档。

    链接:https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Passive_user_reply_message.html

网站服务端

想要微信服务端成功回调,服务端必须外网可以访问,同时微信限制了端口只能是 80 或 443 ,因此只有两种选择 。

  1. 拥有自己的云服务器(这里推荐我司阿里云服务器,如果只是学习体验,抢占式实例低配置一小时也就2毛钱左右,可以用于测试)。
  2. 用内网穿透软件生成外网代理(一般 80 端口都需要收费)。

具体开发

配置微信公众号

可以在微信测试号平台上配置用于测试。

链接:https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index

项目总体结构

项目使用 SpringBoot 3.2.3 + Java 21 进行开发,这里为了方便演示,在一个 Maven 项目中完成所有代码。本文步骤中只会给出关键代码部分,完整代码可以在文末的 GitHub 地址中找到。

下面是项目总体结构:

├── pom.xml
└── src
    └── main
        ├── java
        │   └── com
        │       └── wdbyte
        │           └── weixin
        │               ├── SpringBootApp.java
        │               ├── config
        │               │   └── JwtFilter.java   # JWT 身份认证拦截器
        │               ├── controller
        │               │   ├── WeixinServerController.java # 微信服务端调用接口
        │               │   └── WeixinUserController.java  # 浏览器调用接口
        │               ├── model
        │               │   ├── ApiResult.java     
        │               │   ├── ReceiveMessage.java  # 微信消息封装类
        │               │   └── WeixinQrCode.java # 微信二维码 Ticket 封装类
        │               ├── service
        │               │   ├── WeixinUserService.java # 微信调用处理类
        │               │   └── impl
        │               │       └── WeixinUserServiceImpl.java
        │               └── util
        │                   ├── AesUtils.java # AES 加密工具类
        │                   ├── ApiResultUtil.java
        │                   ├── HttpUtil.java # HTTP 工具类
        │                   ├── JwtUtil.java # JWT 工具类
        │                   ├── KeyUtils.java 
        │                   ├── WeixinApiUtil.java # 微信 API 工具类,如获取 AccessToken
        │                   ├── WeixinMsgUtil.java # 微信消息工具类
        │                   ├── WeixinQrCodeCacheUtil.java # 微信二维码Ticket缓存
        │                   └── XmlUtil.java 
        └── resources
            ├── application.properties #配置文件
            ├── static
            └── templates

WeixinServerControllerWeixinUserController 暴漏了三个 API。

/weixin/check :用于对接微信服务端,接收微信服务端的调用。

/user/qrcode: 用于获取二维码图片信息

/user/login/qrcode: 用于校验是否扫描成功,成功则返回身份认证后的 JWT 字符串。

项目公众号信息配置

application.properties 中配置公众号所需的配置。

server.port=
weixin.appid=
weixin.appsecret=
weixin.token=

ase.util.secret=
key.jwt.secret=

验证签名

开发者提交信息后,微信服务器向填写的 URL 发送 Get 请求,携带参数如下:

参数 描述
signature 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
timestamp 时间戳
nonce 随机数
echostr 随机字符串

开发者需要对 signature 进行校验,判断是否来自微信服务器,公众号相关的其他事件如消息、关注、扫码等一样会回调配置的 URL ,只不过这时是 POST 请求。

验签逻辑查看微信文档:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html

Java 实现如下:

// com.wdbyte.weixin.service.impl.WeixinUserServiceImpl.java

@Value("${weixin.token}")
private String token;

@Override
public void checkSignature(String signature, String timestamp, String nonce) {
    String[] arr = new String[] {token, timestamp, nonce};
    Arrays.sort(arr);
    StringBuilder content = new StringBuilder();
    for (String str : arr) {
        content.append(str);
    }
    String tmpStr = DigestUtils.sha1Hex(content.toString());
    if (tmpStr.equals(signature)) {
        log.info("check success");
        return;
    }
    log.error("check fail");
    throw new RuntimeException("check fail");
}

获取 Access Token

获取带有 Ticket 的公众号二维码之前,需要先获取公众号的 Access Token,这是调用微信公众号所有接口的前提。 Access Token 每日调用次数有限,应该进行缓存。

// com.wdbyte.weixin.util.WeixinApiUtil.java
@Value("${weixin.appid}")
public String appId;

@Value("${weixin.appsecret}")
public String appSecret;

private static String ACCESS_TOKEN = null;
private static LocalDateTime ACCESS_TOKEN_EXPIRE_TIME = null;

/**
 * 获取 access token
 *
 * @return
 */
public synchronized String getAccessToken() {
    if (ACCESS_TOKEN != null && ACCESS_TOKEN_EXPIRE_TIME.isAfter(LocalDateTime.now())) {
        return ACCESS_TOKEN;
    }
    String api = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret="
        + appSecret;
    String result = HttpUtil.get(api);
    JSONObject jsonObject = JSON.parseObject(result);
    ACCESS_TOKEN = jsonObject.getString("access_token");
    ACCESS_TOKEN_EXPIRE_TIME = LocalDateTime.now().plusSeconds(jsonObject.getLong("expires_in") - 10);
    return ACCESS_TOKEN;
}

生成登录二维码

使用 Access Token 获取二维码 Ticket 用来换取二维码图片。

// com.wdbyte.weixin.util.WeixinApiUtil.java
private static String QR_CODE_URL_PREFIX = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=";

/**
 * 二维码 Ticket 过期时间
 */
private static int QR_CODE_TICKET_TIMEOUT = 10 * 60;


/**
 * 获取二维码 Ticket
 *
 * https://developers.weixin.qq.com/doc/offiaccount/Account_Management/Generating_a_Parametric_QR_Code.html
 *
 * @return
 */
public WeixinQrCode getQrCode() {
    String api = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + getAccessToken();
    String jsonBody = String.format("{\n"
        + "  \"expire_seconds\": %d,\n"
        + "  \"action_name\": \"QR_STR_SCENE\",\n"
        + "  \"action_info\": {\n"
        + "    \"scene\": {\n"
        + "      \"scene_str\": \"%s\"\n"
        + "    }\n"
        + "  }\n"
        + "}", QR_CODE_TICKET_TIMEOUT, KeyUtils.uuid32());
    String result = HttpUtil.post(api, jsonBody);
    log.info("get qr code params:{}", jsonBody);
    log.info("get qr code result:{}", result);
    WeixinQrCode weixinQrCode = JSON.parseObject(result, WeixinQrCode.class);
    weixinQrCode.setQrCodeUrl(QR_CODE_URL_PREFIX + URI.create(weixinQrCode.getTicket()).toASCIIString());
    return weixinQrCode;
}
class WeixinQrCode {
    private String ticket;
    private Long expireSeconds;
    private String url;
    private String qrCodeUrl;
}

响应内容格式如下:

{
  "ticket": "gQH47joAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL2taZ2Z3TVRtNzJXV1Brb3ZhYmJJAAIEZ23sUwMEmm3sUw==",
  "expire_seconds": 60,
  "url": "http://weixin.qq.com/q/kZgfwMTm72WWPkovabbI"
}

其中 Ticket 就是二维码凭证,用户扫码后微信会把此 Ticket 回调给网站服务端。可以在下面的链接后面拼上 Ticket 换取二维码图片。

https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=

扫码回调与身份绑定

用户扫码后,微信服务端会把二维码鞋带的 Ticket 和用户的身份标识作为消息内容回调到网站服务器。

格式如下:

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

其中 FromUserName 是用户身份标识,EventKeyqrscene_标识扫码,Ticket 则是二维码的 Ticket。至此,服务端就可以识别出二维码是被哪个用户扫码了。绑定 Ticket 和用户身份标识。

注:FromUserName 是唯一的用户身份标识,同一个用户每次扫描的 FromUserName 相同。

浏览器轮询扫描状态

浏览器鞋带 Ticket 信息不断的轮询 /user/login/qrcode 接口查看 Ticket 是否被扫描成功,如果通过 Ticket 可以查到用户身份标识,说明二维码被扫描成功,返回用户信息。登录完成。

扫码登录测试

浏览器不断的轮询 https://api.wdbyte.com/user/login/qrcode?ticket=Ticket值 获取扫码状态。

二维码尚未扫描,则返回:

{
  "code": -1,
  "data": "check faild",
  "message": "error"
}

微信扫码关注公众号。

扫码成功后轮询接口会响应 JWT 格式的身份信息,这里使用了 AES 对 JWT 进行了加密。

{
  "code": 200,
  "data": "mihzE8Z1Y9t2EoppNSzzytV4TOgn+Nc50ORZjsW/oVkxchL4EzGA6rr1tQ0Q7J24Ipm4otjCYf95Nu8JbV31Q/ImKvlta3f5bgvOdWSlO2tNvOwqgzBSItABohbCLVLxjGCci4VtNaEFgQjoDjc1uhwP/GCSohVFc7csO9SxpOm8HKtlRhATjwPrtiQ9iLErfsUs27I0k5OHp55AzuQOYCvza//i3wk8nlv/MDkk7y1nvsZkllyKQGHPB4Ulcraz",
  "message": "success"
}

至此,登录完成。

完整代码: github.com/niumoo/JavaNotes/tree/master/springboot/springboot-weixin-qrcode-login

一如既往,文章中代码存放在 Github.com/niumoo/javaNotes.

本文收录于 Github.com/niumoo/JavaNotes,Java 系列文档,数据结构与算法!
本文收录于网站:https://www.wdbyte.com/,我的公众号:程序猿阿朗

标签:扫码,weixin,微信,二维码,即入,com,服务端
From: https://www.cnblogs.com/niumoo/p/18118422

相关文章

  • 移动支付新时代——低代码如何对接支付宝和微信支付
    前言移动支付已经成为现代生活中不可或缺的一部分。随着技术的不断发展和普及,越来越多的人通过手机进行支付。支付宝和微信支付作为中国最主要的移动支付平台,已经成为人们日常生活中最常用的支付方式之一。然而,对于一些初创企业或者中小型企业来说,要接入支付宝和微信支付并不是一......
  • 微信小程序开发之数据绑定
    1、什么是数据绑定?为什么要进行数据绑定?数据绑定的好处?真实项目中,数据通常会放置在服务器中,通过HTTP请求来访问服务器提供的RESTFULAPI,实现数据获取。微信小程序入门开发时,我们将页面里的内容全都直接编码在wxml文件中,这种代码写法称为“硬编码”,数据直接暴露在wxml文件中,是......
  • 基于深度学习的生活垃圾智能分类系统(微信小程序+YOLOv5+训练数据集+开题报告+中期检查
    摘要        本文基于Python技术,搭建了YOLOv5s深度学习模型,并基于该模型研发了微信小程序的垃圾分类应用系统。本项目的主要工作如下:    (1)调研了移动端垃圾分类应用软件动态,并分析其优劣势;分析了深度学习在垃圾分类领域的相关应用,着重研究了YOLO系列的工作原......
  • java毕业设计基于微信点餐系统小程序[附源码]
    本系统(程序+源码)带文档lw万字以上  文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义标题:基于微信的点餐系统小程序设计与实现在移动互联网技术迅猛发展的今天,传统的餐饮服务方式正逐步向智能化、便捷化转型。随着微信生态系统的不断完善,微信小程序......
  • SpringBoot集成微信支付(JAVA)
    微信支付(Java)目录微信支付(Java)简介:登录微信公众平台(JSAPI支付):注意事项:添加依赖:application.yaml:WeixinPayController:PaymentService:PaymentServiceImpl:实体类PaymentJSAPI:简介:        Springboot项目集成微信支付(JSAPI),用于微信公众号对接支付功......
  • SpringBoot集成微信支付(JAVA)
    微信支付(Java)目录微信支付(Java)简介:登录微信公众平台(JSAPI支付):注意事项:添加依赖:application.yaml:WeixinPayController:PaymentService:PaymentServiceImpl:实体类PaymentJSAPI:简介:        Springboot项目集成微信支付(JSAPI),用于微信公众号对接支付功能......
  • Go 实战|使用 Wails 构建轻量级的桌面应用:仿微信登录界面 Demo
    概述本文探讨Wails框架的使用,从搭建环境到开发,再到最终的构建打包,本项目源码GitHub地址:https://github.com/mazeyqian/go-run-wechat-demo前言Wails是一个跨平台桌面应用开发框架,他允许开发者利用Go的性能优势,并结合任何前端技术栈,如React、Vue或Svelte,来创建桌面应......
  • Taro微信小程序--压缩图片组件
    图片压缩组件ImageCompress组件用于在Taro微信小程序中对图片进行压缩,以提高性能和优化加载。该组件利用了Taro框架来实现图片压缩功能。1,用法在页面导入ImageCompress组件。importImageCompressfrom'path/to/ImageCompress';传入指定参数<ImageCompressi......
  • 微信小程序开发 基础知识(持续更新中~)
    ......
  • 车源宝微信小程序源码
    源码介绍车源宝微信小程序源码images—存放项目图片文件pages—存放项目页面相关文件store—存放数据接口文件utils—存放时间格式化等文件演示截图源码下载https://download.csdn.net/download/huayula/89082980......