<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>身份认证 on 豆子技术站</title><link>https://blog.91demo.top/tags/%E8%BA%AB%E4%BB%BD%E8%AE%A4%E8%AF%81.html</link><description>Recent content in 身份认证 on 豆子技术站</description><generator>Hugo -- 0.155.1</generator><language>zh-cn</language><lastBuildDate>Tue, 11 Mar 2025 07:22:34 +0000</lastBuildDate><atom:link href="https://blog.91demo.top/tags/%E8%BA%AB%E4%BB%BD%E8%AE%A4%E8%AF%81/index.xml" rel="self" type="application/rss+xml"/><item><title>构建自定义证码登录系统及研究语音验证码实战</title><link>https://blog.91demo.top/web/vcode_login.html</link><pubDate>Tue, 11 Mar 2025 07:22:34 +0000</pubDate><guid>https://blog.91demo.top/web/vcode_login.html</guid><description>&lt;p&gt;当我使用小程序码登录网站时，我发现了一个问题，在手机端不方便登录。我们都知道手机号验证码可以登录网站，但是我没有资源去实现手机号验证码功能，我使用一个变通的方案，在手机端不使用手机号验证码也能登录。&lt;/p&gt;
&lt;h3 id="小程序实现验证码登录"&gt;小程序实现验证码登录&lt;/h3&gt;
&lt;p&gt;它的核心还是鉴权，我在小程序端制作了一个获取验证码界面，它可以生成模拟编号和验证码。当用户点击获取验证码时，会向后台请求返回编号和验证码，后台这个时候会记录为哪个用户openid生成了哪个验证码。那为什么不单单使用验证码呢？还要再添加一个编号，不麻烦吗？因为单单使用验证码会发生撞车的可能。要知道，验证码一般4位或者6位，很容易被暴力攻击的。&lt;/p&gt;
&lt;p&gt;当用户在网站端输入编号和验证码时，后端会校验是否存在这对编号和验证码，如果校验正确，将取出openid并绑定到sessionID上，然后返回给前端，存入cookie中。可以看看前面的文章，扫描二维码登录，同样的道理。&lt;/p&gt;
&lt;p&gt;除了在小程序生成验证码外，我们还可以在公众号中发送消息获取验证码。它其实也是使用了微信的账号体系。&lt;/p&gt;
&lt;h3 id="公众号实现验证码登录"&gt;公众号实现验证码登录&lt;/h3&gt;
&lt;p&gt;要知道公众号不仅是内容分发平台，更是一个强大的&lt;strong&gt;身份认证中间件&lt;/strong&gt;。我们使用发送消息来获取验证码信息。&lt;/p&gt;
&lt;h4 id="1-握手与回调-webhook"&gt;1. 握手与回调 (Webhook)&lt;/h4&gt;
&lt;p&gt;当你在公众号消息发送验证码三个字时，微信会推送事件到你的服务器。我使用go对接了微信公众号消息。&lt;/p&gt;
&lt;p&gt;要在 Go 中接收微信消息，你必须先在微信公众平台配置一个 &lt;strong&gt;服务器地址 (URL)&lt;/strong&gt;。** 微信会向你的 URL 发送一个 GET 请求，包含签名、随机数等。你必须按照规定的算法计算并返回正确的 &lt;code&gt;echostr&lt;/code&gt;，这被称为“服务器验证”。 验证通过后，每当用户发送消息，微信服务器就会以 POST 方式将消息体推送给你。&lt;/p&gt;
&lt;h4 id="2-解析-xml-数据"&gt;2. 解析 XML 数据&lt;/h4&gt;
&lt;p&gt;与现代 API 不同，微信公众号的推送采用的是 &lt;strong&gt;XML&lt;/strong&gt; 格式。Go 的标准库 &lt;code&gt;encoding/xml&lt;/code&gt; 提供了强大的解析能力：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;type&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;WxMsg&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;ToUserName&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`xml:&amp;#34;ToUserName&amp;#34;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;FromUserName&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`xml:&amp;#34;FromUserName&amp;#34;`&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 这就是用户的 OpenID&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;Content&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;string&lt;/span&gt; &lt;span style="color:#e6db74"&gt;`xml:&amp;#34;Content&amp;#34;`&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 用户发来的文字&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="3-验证码生存逻辑"&gt;3. 验证码生存逻辑&lt;/h4&gt;
&lt;p&gt;当用户发送“验证码”关键字时，我们的 Go 后端会生成一个 4-6 位的随机数和一个编号。并将消息中的 OpenID 与 编号和随机数 存入 Redis，并设置 TTL（如 5 分钟）。然后通过 XML 响应将验证码发回给用户。&lt;/p&gt;
&lt;h4 id="4-身份绑定完成登录"&gt;4. 身份绑定，完成登录&lt;/h4&gt;
&lt;p&gt;我们在Web HTML页面提供了登录表单，提供编号和验证码输入框。用户输入编号和验证码后提交到后端，后端从 Redis 中根据编号和验证码反查 OpenID，若存在且有效，则代表身份验证成功，返回包含身份的TOKEN。&lt;/p&gt;</description></item></channel></rss>