<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0"><channel><title>Halo - 强大易用的开源建站工具 | 应用市场 | 统一身份认证 | 版本发布</title><link>https://www.halo.run</link><atom:link href="https://www.halo.run/feed/app-store/apps/app-1dondjfv/releases.xml" rel="self" type="application/rss+xml"/><description>Halo - 强大易用的开源建站工具 | 应用市场 | 统一身份认证 | 版本发布</description><generator>Halo v2.25.4</generator><language>zh-cn</language><image><url>https://www.halo.run/upload/logo.png</url><title>Halo - 强大易用的开源建站工具 | 应用市场 | 统一身份认证 | 版本发布</title><link>https://www.halo.run</link></image><lastBuildDate>Sat, 11 Jul 2026 08:20:08 GMT</lastBuildDate><follow_challenge><feedId>69597013489248256</feedId><userId>41706424548048896</userId></follow_challenge><item><title><![CDATA[统一身份认证 1.0.0 发布]]></title><link>https://www.halo.run/store/apps/app-1dondjfv/releases/app-release-pq8t3czq</link><description><![CDATA[<img src="https://www.halo.run/plugins/feed/assets/telemetry.gif?title=%E7%BB%9F%E4%B8%80%E8%BA%AB%E4%BB%BD%E8%AE%A4%E8%AF%81%201.0.0%20%E5%8F%91%E5%B8%83&amp;url=/store/apps/app-1dondjfv/releases/app-release-pq8t3czq" width="1" height="1" alt="" style="opacity:0;">
<h1 id="%E7%BB%9F%E4%B8%80%E8%BA%AB%E4%BB%BD%E8%AE%A4%E8%AF%81" tabindex="-1">统一身份认证</h1>
<p>为多个 Halo 站点提供“身份中心 + 接入站”的单点登录能力。一个站点作为身份中心统一承接登录与授权，其它 Halo 站点作为接入站跳转到身份中心完成认证，并在回调后建立本站登录态、绑定本地用户、同步用户资料和映射本地角色。</p>
<h2 id="%E5%8A%9F%E8%83%BD%E6%BC%94%E7%A4%BA" tabindex="-1">功能演示</h2>
<table>
 <thead>
  <tr>
   <th>地址</th>
   <th>账号/密码</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td><a href="https://demo.muyin.site/console">演示站</a></td>
   <td>demo/demo123.</td>
  </tr>
 </tbody>
</table>
<h2 id="%E4%BA%A4%E6%B5%81%E7%BE%A4" tabindex="-1">交流群</h2>
<p><a href="https://qm.qq.com/q/wuC7NZr0sw">点击链接加入群聊【halo博客-lywq插件】</a></p>
<img src="https://www.halo.run/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https%3A%2F%2Fgithub.com%2Fuser-attachments%2Fassets%2Fbf162401-07fd-49ec-b50f-5218c9510937&amp;size=m" style="height: 400px !important; width: auto; object-fit: contain;">
<h2 id="%E6%8F%92%E4%BB%B6%E4%BB%8B%E7%BB%8D" tabindex="-1">插件介绍</h2>
<p><code>halo-plugin-sso</code> 适合一组 Halo 站点共用同一套账号体系的场景，例如主站、文档站、社区站、资源站分别部署，但希望用户只使用一个中心账号登录。</p>
<p>插件采用 Authorization Code + PKCE 的登录闭环：</p>
<ol>
 <li>接入站发起登录。</li>
 <li>用户被跳转到身份中心授权端点。</li>
 <li>身份中心确认用户登录状态和授权条件。</li>
 <li>身份中心向接入站回调授权码。</li>
 <li>接入站使用授权码换取 Token，拉取用户身份信息。</li>
 <li>接入站绑定或创建本地 Halo 用户，映射角色并建立本地登录态。</li>
</ol>
<p>当前能力包括：</p>
<ul>
 <li>身份中心模式：管理接入站、签发授权码、提供 Token 和 UserInfo、下发中心标准角色。</li>
 <li>接入站模式：跳转身份中心登录、处理回调、绑定或创建本地用户、同步用户资料、映射本地角色。</li>
 <li>登录入口控制：接入站可选择自动跳转 SSO 登录，也可保留 Halo 默认登录页并手动选择“统一身份认证”。</li>
 <li>动态认证提供者信息：接入站登录页展示的 <code>displayName</code>、<code>description</code>、<code>logo</code>、<code>website</code> 会从身份中心站点基础信息同步。</li>
 <li>角色映射：身份中心下发中心角色，接入站按映射规则转换为本站本地角色。</li>
 <li>审计日志：记录接入站登录成功、失败、失败原因，并支持筛选、聚合、手动清理和自动清理。</li>
 <li>用户绑定：记录中心账号与接入站本地用户的绑定关系。</li>
</ul>
<h2 id="%E9%80%82%E7%94%A8%E7%8E%AF%E5%A2%83" tabindex="-1">适用环境</h2>
<ul>
 <li>Halo <code>&gt;= 2.25.0</code></li>
 <li>Java 21+</li>
 <li>一个可被接入站访问的身份中心站点地址，例如 <code>https://auth.example.com</code></li>
 <li>接入站需要有稳定外部访问地址，例如 <code>https://blog.example.com</code></li>
</ul>
<p>生产环境建议使用 HTTPS。开发调试时可在插件设置中临时开启“开发环境允许 HTTP localhost”，但别把这个当生产方案，真上生产这么干就有点硬莽了。</p>
<h2 id="%E5%BF%AB%E9%80%9F%E5%BC%80%E5%A7%8B" tabindex="-1">快速开始</h2>
<p>完整接入至少需要两个 Halo 站点：</p>
<ul>
 <li>站点 A：身份中心。</li>
 <li>站点 B：接入站。</li>
</ul>
<p>下面用：</p>
<ul>
 <li>身份中心：<code>https://auth.example.com</code></li>
 <li>接入站：<code>https://blog.example.com</code></li>
</ul>
<h3 id="1.-%E5%AE%89%E8%A3%85%E6%8F%92%E4%BB%B6" tabindex="-1">1. 安装插件</h3>
<p>在身份中心站点和每个接入站点都安装并启用本插件。</p>
<p>构建插件：</p>
<pre><code class="language-bash">./gradlew build
</code></pre>
<p>构建完成后，插件 JAR 位于：</p>
<pre><code class="language-text">build/libs/
</code></pre>
<p>将 JAR 上传到 Halo 后台插件管理并启用。</p>
<h3 id="2.-%E9%85%8D%E7%BD%AE%E8%BA%AB%E4%BB%BD%E4%B8%AD%E5%BF%83" tabindex="-1">2. 配置身份中心</h3>
<p>进入身份中心站点后台：</p>
<pre><code class="language-text">控制台 -&gt; 插件 -&gt; 统一身份认证 -&gt; 设置
</code></pre>
<p>在“基础设置”中配置：</p>
<table>
 <thead>
  <tr>
   <th>配置项</th>
   <th>建议值</th>
   <th>说明</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td>运行模式</td>
   <td>身份中心模式</td>
   <td>当前站点负责统一登录和授权</td>
  </tr>
  <tr>
   <td>中心标准角色</td>
   <td><code>subscriber</code>、<code>author</code>、<code>editor</code> 等</td>
   <td>只有选中的中心角色会下发给接入站</td>
  </tr>
  <tr>
   <td>要求邮箱已验证</td>
   <td>开启</td>
   <td>未验证邮箱的中心用户不允许跨站登录</td>
  </tr>
 </tbody>
</table>
<p>然后进入插件控制台页面：</p>
<pre><code class="language-text">控制台 -&gt; 系统工具 -&gt; 统一身份认证
</code></pre>
<p>在“接入站”区域创建一个接入站：</p>
<table>
 <thead>
  <tr>
   <th>字段</th>
   <th>示例</th>
   <th>说明</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td>接入站名称</td>
   <td>我的博客</td>
   <td>控制台展示用</td>
  </tr>
  <tr>
   <td>站点地址</td>
   <td><code>https://blog.example.com</code></td>
   <td>接入站外部访问地址</td>
  </tr>
  <tr>
   <td>Redirect URI</td>
   <td><code>https://blog.example.com/apis/public.sso.muyin.site/v1alpha1/client/callback</code></td>
   <td>接入站回调地址</td>
  </tr>
  <tr>
   <td>启用状态</td>
   <td>开启</td>
   <td>关闭后该接入站不能继续登录</td>
  </tr>
 </tbody>
</table>
<p>创建成功后会得到：</p>
<ul>
 <li><code>Client ID</code></li>
 <li><code>Client Secret</code></li>
</ul>
<p><code>Client Secret</code> 只展示一次，复制保存好。这个东西丢了就重新生成或重建接入站，别指望页面再掏出来给你看。</p>
<h3 id="3.-%E9%85%8D%E7%BD%AE%E6%8E%A5%E5%85%A5%E7%AB%99" tabindex="-1">3. 配置接入站</h3>
<p>进入接入站后台：</p>
<pre><code class="language-text">控制台 -&gt; 插件 -&gt; 统一身份认证 -&gt; 设置
</code></pre>
<p>在“基础设置”中配置：</p>
<table>
 <thead>
  <tr>
   <th>配置项</th>
   <th>示例</th>
   <th>说明</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td>运行模式</td>
   <td>接入站模式</td>
   <td>当前站点负责跳转登录和建立本地登录态</td>
  </tr>
  <tr>
   <td>身份中心地址</td>
   <td><code>https://auth.example.com</code></td>
   <td>身份中心站点外部地址</td>
  </tr>
  <tr>
   <td>Client ID</td>
   <td>从身份中心复制</td>
   <td>对应身份中心创建的接入站</td>
  </tr>
  <tr>
   <td>Client Secret</td>
   <td>从身份中心复制</td>
   <td>服务端换取 Token 使用</td>
  </tr>
  <tr>
   <td>默认本地角色</td>
   <td><code>guest</code> 或其它低权限角色</td>
   <td>未命中角色映射时使用</td>
  </tr>
  <tr>
   <td>登录时同步用户资料</td>
   <td>按需开启</td>
   <td>同步邮箱、用户名、展示名称和头像</td>
  </tr>
  <tr>
   <td>自动跳转 SSO 登录</td>
   <td>按需开启</td>
   <td>开启后访问 <code>/login</code> 自动跳转身份中心</td>
  </tr>
 </tbody>
</table>
<p>接入站保存配置后，插件会定期从身份中心同步认证提供者信息。同步来源是身份中心 Halo 系统基础设置：</p>
<table>
 <thead>
  <tr>
   <th>AuthProvider 字段</th>
   <th>身份中心来源</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td><code>displayName</code></td>
   <td>站点标题</td>
  </tr>
  <tr>
   <td><code>description</code></td>
   <td>站点副标题</td>
  </tr>
  <tr>
   <td><code>logo</code></td>
   <td>站点 Logo，未配置时使用 favicon，再未配置时使用插件默认图标</td>
  </tr>
  <tr>
   <td><code>website</code></td>
   <td>站点外部访问地址</td>
  </tr>
 </tbody>
</table>
<p>如果身份中心临时不可用，接入站会保留上一次同步成功的本地认证提供者信息，不会把登录入口改成空壳。</p>
<h3 id="4.-%E9%85%8D%E7%BD%AE%E8%A7%92%E8%89%B2%E6%98%A0%E5%B0%84" tabindex="-1">4. 配置角色映射</h3>
<p>进入接入站插件控制台：</p>
<pre><code class="language-text">控制台 -&gt; 系统工具 -&gt; 统一身份认证 -&gt; 角色映射
</code></pre>
<p>创建映射关系：</p>
<table>
 <thead>
  <tr>
   <th>中心角色</th>
   <th>本地角色</th>
   <th>说明</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td><code>subscriber</code></td>
   <td><code>guest</code></td>
   <td>普通用户</td>
  </tr>
  <tr>
   <td><code>author</code></td>
   <td><code>contributor</code></td>
   <td>投稿或作者</td>
  </tr>
  <tr>
   <td><code>editor</code></td>
   <td><code>editor</code></td>
   <td>编辑</td>
  </tr>
 </tbody>
</table>
<p>规则说明：</p>
<ul>
 <li>身份中心只下发“中心标准角色”中允许的角色。</li>
 <li>接入站只按启用状态的映射规则转换角色。</li>
 <li>未命中映射时使用“默认本地角色”。</li>
 <li>已有本地用户登录时，插件会追加缺失角色，不会清空用户已有本地角色。</li>
</ul>
<h2 id="%E7%99%BB%E5%BD%95%E6%95%99%E7%A8%8B" tabindex="-1">登录教程</h2>
<h3 id="%E8%87%AA%E5%8A%A8-sso-%E7%99%BB%E5%BD%95" tabindex="-1">自动 SSO 登录</h3>
<p>适合希望接入站完全交给身份中心登录的场景。</p>
<ol>
 <li>在接入站插件设置中开启“自动跳转 SSO 登录”。</li>
 <li>用户访问接入站 <code>/login</code>。</li>
 <li>插件自动跳转到身份中心授权页。</li>
 <li>用户在身份中心登录。</li>
 <li>登录成功后回到接入站，并建立接入站本地登录态。</li>
</ol>
<p>如果需要临时访问接入站本地登录页，可以访问：</p>
<pre><code class="language-text">/login?sso_local=1
</code></pre>
<h3 id="%E6%89%8B%E5%8A%A8%E9%80%89%E6%8B%A9-sso-%E7%99%BB%E5%BD%95" tabindex="-1">手动选择 SSO 登录</h3>
<p>适合接入站需要同时保留本地登录和 SSO 登录的场景。</p>
<ol>
 <li>在接入站插件设置中关闭“自动跳转 SSO 登录”。</li>
 <li>到 Halo 的认证提供者配置中启用 <code>muyin-sso</code>。</li>
 <li>用户访问接入站 <code>/login</code>。</li>
 <li>用户在登录页选择“统一身份认证”。</li>
 <li>插件跳转身份中心完成登录。</li>
</ol>
<p>手动入口由插件声明的 <code>AuthProvider</code> 提供：</p>
<pre><code class="language-text">metadata.name: muyin-sso
authenticationUrl: /apis/public.sso.muyin.site/v1alpha1/client/login
</code></pre>
<h3 id="%E6%8C%87%E5%AE%9A%E7%99%BB%E5%BD%95%E5%90%8E%E8%BF%94%E5%9B%9E%E5%9C%B0%E5%9D%80" tabindex="-1">指定登录后返回地址</h3>
<p>接入站登录入口支持 <code>return_url</code> 参数：</p>
<pre><code class="language-text">/apis/public.sso.muyin.site/v1alpha1/client/login?return_url=/archives/demo
</code></pre>
<p>登录完成后会回到指定地址。插件会校验返回地址，只允许本站相对路径，避免被拿去做开放重定向。这个地方不校验就等于给钓鱼链接递刀，不能省。</p>
<h2 id="%E5%AE%A1%E8%AE%A1%E6%97%A5%E5%BF%97%E4%B8%8E%E6%B8%85%E7%90%86" tabindex="-1">审计日志与清理</h2>
<p>插件会记录接入站登录过程中的关键结果：</p>
<ul>
 <li>登录成功。</li>
 <li>登录失败。</li>
 <li>Client 校验失败。</li>
 <li>Token 换取失败。</li>
 <li>UserInfo 拉取失败。</li>
 <li>用户创建或绑定失败。</li>
 <li>角色映射结果。</li>
</ul>
<p>在插件控制台的“审计日志”中可以：</p>
<ul>
 <li>按结果筛选：<code>success</code> / <code>failure</code></li>
 <li>按 Client ID 筛选。</li>
 <li>按关键词搜索 subject、email 或 message。</li>
 <li>查看最近失败原因聚合。</li>
 <li>按保留天数执行干跑预览或真实清理。</li>
 <li>查看最近一次清理状态和清理历史。</li>
</ul>
<p>插件设置中可以开启“自动清理过期审计日志”。默认关闭，开启后后台任务会定期按保留天数清理过期日志。</p>
<h2 id="%E5%85%AC%E5%85%B1%E6%8E%A5%E5%8F%A3" tabindex="-1">公共接口</h2>
<p>接入站和身份中心之间主要使用以下接口。</p>
<p>身份中心 OAuth API：</p>
<table>
 <thead>
  <tr>
   <th>方法</th>
   <th>路径</th>
   <th>说明</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td><code>GET</code></td>
   <td><code>/apis/public.sso.muyin.site/v1alpha1/oauth/authorize</code></td>
   <td>OAuth 授权端点</td>
  </tr>
  <tr>
   <td><code>POST</code></td>
   <td><code>/apis/public.sso.muyin.site/v1alpha1/oauth/token</code></td>
   <td>使用授权码换取 Token</td>
  </tr>
  <tr>
   <td><code>GET</code></td>
   <td><code>/apis/public.sso.muyin.site/v1alpha1/oauth/userinfo</code></td>
   <td>获取中心用户信息和中心角色</td>
  </tr>
  <tr>
   <td><code>GET</code></td>
   <td><code>/apis/public.sso.muyin.site/v1alpha1/oauth/notice</code></td>
   <td>授权拒绝提示页</td>
  </tr>
 </tbody>
</table>
<p>公共辅助 API：</p>
<table>
 <thead>
  <tr>
   <th>方法</th>
   <th>路径</th>
   <th>说明</th>
  </tr>
 </thead>
 <tbody>
  <tr>
   <td><code>GET</code></td>
   <td><code>/apis/public.sso.muyin.site/v1alpha1/metadata</code></td>
   <td>获取身份中心认证提供者元信息</td>
  </tr>
  <tr>
   <td><code>GET</code></td>
   <td><code>/apis/public.sso.muyin.site/v1alpha1/roles/list</code></td>
   <td>获取身份中心可下发角色列表</td>
  </tr>
  <tr>
   <td><code>GET</code></td>
   <td><code>/apis/public.sso.muyin.site/v1alpha1/client/login</code></td>
   <td>接入站发起 SSO 登录</td>
  </tr>
  <tr>
   <td><code>GET</code></td>
   <td><code>/apis/public.sso.muyin.site/v1alpha1/client/callback</code></td>
   <td>接入站处理 SSO 回调</td>
  </tr>
 </tbody>
</table>
<p>Console API 主要由插件后台页面调用，覆盖接入站管理、角色映射、用户绑定、审计日志和设置读取。开发调试时可查看：</p>
<pre><code class="language-text">api-docs/openapi/v3_0/ssoApis.json
</code></pre>
<h2 id="%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98" tabindex="-1">常见问题</h2>
<h3 id="%E6%8E%A5%E5%85%A5%E7%AB%99%E7%99%BB%E5%BD%95%E5%90%8E%E5%9B%9E%E8%B0%83%E5%A4%B1%E8%B4%A5" tabindex="-1">接入站登录后回调失败</h3>
<p>优先检查身份中心中登记的 Redirect URI 是否和接入站实际地址完全一致。协议、域名、端口、路径都要一致。</p>
<p>标准回调路径为：</p>
<pre><code class="language-text">https://接入站域名/apis/public.sso.muyin.site/v1alpha1/client/callback
</code></pre>
<h3 id="%E8%AE%BF%E9%97%AE%E6%8E%A5%E5%85%A5%E7%AB%99-%2Flogin-%E6%B2%A1%E6%9C%89%E8%B7%B3%E8%BD%AC%E8%BA%AB%E4%BB%BD%E4%B8%AD%E5%BF%83" tabindex="-1">访问接入站 <code>/login</code> 没有跳转身份中心</h3>
<p>检查接入站插件设置：</p>
<ul>
 <li>运行模式必须是“接入站模式”。</li>
 <li>身份中心地址、Client ID、Client Secret 必须填写。</li>
 <li>“自动跳转 SSO 登录”必须开启。</li>
</ul>
<p>如果你关闭了自动跳转，需要在 Halo 认证提供者中启用 <code>muyin-sso</code>，然后在默认登录页手动选择“统一身份认证”。</p>
<h3 id="%E6%89%8B%E5%8A%A8-sso-%E7%99%BB%E5%BD%95%E5%85%A5%E5%8F%A3%E6%B2%A1%E6%9C%89%E5%B1%95%E7%A4%BA" tabindex="-1">手动 SSO 登录入口没有展示</h3>
<p>检查 Halo 认证提供者配置中是否启用了 <code>muyin-sso</code>。插件声明 <code>AuthProvider</code> 不等于 Halo 一定展示它，展示与否由 Halo 的认证提供者启用状态控制。</p>
<h3 id="%E6%8E%A5%E5%85%A5%E7%AB%99%E7%99%BB%E5%BD%95%E9%A1%B5%E5%B1%95%E7%A4%BA%E7%9A%84%E5%90%8D%E7%A7%B0%E5%92%8C-logo-%E4%B8%8D%E5%AF%B9" tabindex="-1">接入站登录页展示的名称和 Logo 不对</h3>
<p>接入站会从身份中心 <code>/metadata</code> 同步认证提供者信息。请检查：</p>
<ul>
 <li>身份中心插件是否为“身份中心模式”。</li>
 <li>接入站能否访问身份中心地址。</li>
 <li>身份中心 Halo 系统基础设置中是否配置了标题、副标题、Logo、外部访问地址。</li>
 <li>身份中心站点外部地址是否正确，尤其是反向代理后的 <code>https</code> 地址。</li>
</ul>
<h3 id="%E7%94%A8%E6%88%B7%E7%99%BB%E5%BD%95%E6%88%90%E5%8A%9F%E4%BD%86%E8%A7%92%E8%89%B2%E4%B8%8D%E7%AC%A6%E5%90%88%E9%A2%84%E6%9C%9F" tabindex="-1">用户登录成功但角色不符合预期</h3>
<p>检查三处：</p>
<ol>
 <li>身份中心“中心标准角色”是否包含该用户角色。</li>
 <li>接入站“角色映射”是否配置并启用。</li>
 <li>接入站“默认本地角色”是否符合预期。</li>
</ol>
<h3 id="%E8%BA%AB%E4%BB%BD%E4%B8%AD%E5%BF%83%E9%80%80%E5%87%BA%E5%90%8E%E6%8E%A5%E5%85%A5%E7%AB%99%E6%B2%A1%E6%9C%89%E9%80%80%E5%87%BA" tabindex="-1">身份中心退出后接入站没有退出</h3>
<p>这是当前设计，不是 bug。插件不做统一退出登录。身份中心退出只影响身份中心本地会话，不会强制接入站本地会话失效。</p>
<h2 id="%E5%BC%80%E5%8F%91" tabindex="-1">开发</h2>
<p>本地开发依赖：</p>
<ul>
 <li>Java 21+</li>
 <li>Node.js 18+</li>
 <li>pnpm</li>
</ul>
<p>启动 Halo 开发服务：</p>
<pre><code class="language-bash">./gradlew haloServer
</code></pre>
<p>前端开发：</p>
<pre><code class="language-bash">cd ui
pnpm install
pnpm dev
</code></pre>
<p>运行测试：</p>
<pre><code class="language-bash">./gradlew test
</code></pre>
<p>构建插件：</p>
<pre><code class="language-bash">./gradlew build
</code></pre>
<p>生成的插件 JAR 在：</p>
<pre><code class="language-text">build/libs/
</code></pre>
<h2 id="%E8%AE%B8%E5%8F%AF%E8%AF%81" tabindex="-1">许可证</h2>
<p><a href="https://www.halo.run/./LICENSE">GPL-3.0</a> © Lywq</p>
<hr>
<p><a href="https://www.halo.run/store/apps/app-1dondjfv/releases/app-release-pq8t3czq">查看版本详情</a></p>]]></description><guid isPermaLink="false">store.halo.run/Release/app-release-pq8t3czq</guid><pubDate>Sat, 27 Jun 2026 08:45:45 GMT</pubDate></item></channel></rss>