如何为打包为Electron桌面应用的Blazor Server创建获取JWT的登录页
可行实现方案
下面直接给两个可落地的方案,优先推荐第一种,适配Electron场景成本最低:
方案1:静态登录页 + 手动启动Blazor SignalR连接(推荐)
实现步骤
- 第一步:在wwwroot目录下新增
login.html作为登录入口,Electron启动时默认加载这个页面
<!-- wwwroot/login.html 核心代码 --> <body> <div> <input type="text" id="username" placeholder="账号"> <input type="password" id="password" placeholder="密码"> <button onclick="login()">登录</button> <span id="errMsg" style="color:red"></span> </div> <script> async function login() { const username = document.getElementById('username').value const password = document.getElementById('password').value try { // 调用远端JWT签发接口拿令牌 const resp = await fetch('你的JWT签发服务地址', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({username, password}) }) if (!resp.ok) throw new Error('账号或密码错误') const {accessToken} = await resp.json() // 存到LocalStorage方便后续刷新等操作使用 localStorage.setItem('access_token', accessToken) // 跳转到Blazor宿主页 location.href = '/index.html' } catch (e) { document.getElementById('errMsg').innerText = e.message } } </script> </body>
- 第二步:修改Blazor宿主页(默认是Pages/_Host.cshtml或者wwwroot/index.html),禁用blazor.server.js自动启动,手动启动时携带JWT
<!-- 引用blazor.server.js时关闭自动启动 --> <script src="_framework/blazor.server.js" autostart="false"></script> <script> document.addEventListener('DOMContentLoaded', async () => { const accessToken = localStorage.getItem('access_token') // 没有令牌直接退回登录页 if (!accessToken) { location.href = '/login.html' return } // 手动启动Blazor,配置SignalR连接参数,把JWT放在查询参数 await Blazor.start({ configureSignalR: function (builder) { builder.withUrl('/_blazor', { accessTokenFactory: () => accessToken }) } }) }) </script>
- 第三步:调整你之前写的JwtBearer配置,去掉硬编码的令牌,优先取SignalR带过来的令牌
options.Events = new JwtBearerEvents { OnMessageReceived = context => { // SignalR默认会把accessTokenFactory返回的令牌放在access_token查询参数 var accessToken = context.Request.Query["access_token"]; // 也兼容从Authorization头取,适配其他HTTP接口调用 if(string.IsNullOrEmpty(accessToken) && context.Request.Headers.ContainsKey("Authorization")) { accessToken = context.Request.Headers["Authorization"].ToString().Replace("Bearer ", ""); } context.Token = accessToken; return Task.CompletedTask; } };
- 第四步:在Program.cs/Startup.cs里配置静态文件路由,确保login.html能被正常访问,不需要认证即可访问
// 放在认证中间件之前 app.UseStaticFiles(); // 配置login.html允许匿名访问 app.UseWhen(context => context.Request.Path.StartsWithSegments("/login.html"), appBuilder => { appBuilder.Use(async (context, next) => { await next(); }); });
方案2:Blazor内置登录组件 + Circuit绑定令牌
如果不想做单独的静态登录页,可以直接在Blazor里做登录组件,步骤如下:
- 全局取消默认的认证拦截,允许未认证用户访问Blazor应用
- 首页加判断,未认证时渲染登录组件,用户输入账号密码后调用JWT接口拿到令牌
- 拿到令牌后调用
NavigationManager.NavigateTo("/?access_token=" + token, forceLoad: true),强制重载页面,把令牌放在查询参数里 - OnMessageReceived事件里优先取查询参数的令牌,逻辑和方案1一致
之前Razor Pages方案无法落地的问题修复
如果要继续用你之前的Razor Pages登录方案,只需要补充两个配置即可:
- 在服务注册时加
services.AddRazorPages(); - 在中间件配置里加
app.MapRazorPages();放在Blazor路由配置之前,Razor页面就能正常访问了。
内容的提问来源于stack exchange,提问作者tinmac
相关产品推荐
相关产品推荐

