目录:
- OpenID 与 OAuth2 基础知识
- Blazor wasm Google 登录
- Blazor wasm Gitee 码云登录
- Blazor SSR/WASM IDS/OIDC 单点登录授权实例1-建立和配置IDS身份验证服务
- Blazor SSR/WASM IDS/OIDC 单点登录授权实例2-登录信息组件wasm
- Blazor SSR/WASM IDS/OIDC 单点登录授权实例3-服务端管理组件
- Blazor SSR/WASM IDS/OIDC 单点登录授权实例4 - 部署服务端/独立WASM端授权
- Blazor SSR/WASM IDS/OIDC 单点登录授权实例5 - Blazor hybird app 端授权
- Blazor SSR/WASM IDS/OIDC 单点登录授权实例5 - Winform 端授权
源码
WinFormsOIDC
建立winform项目
安装包 IdentityModel.OidcClient 以及 Microsoft.Web.WebView2 , 项目使用x64运行
<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>WinExe</OutputType><TargetFramework>net8.0-windows</TargetFramework><Nullable>enable</Nullable><UseWindowsForms>true</UseWindowsForms><ImplicitUsings>enable</ImplicitUsings></PropertyGroup><ItemGroup><PackageReference Include="IdentityModel.OidcClient" Version="5.2.1" /><PackageReference Include="Microsoft.Web.WebView2" Version="1.0.2210.55" /></ItemGroup></Project>
拖放一个TextBox控件
Form1.cs 代码
using IdentityModel.OidcClient;
using System.Text;
using WinFormsWebView2;namespace WinFormsOIDC;public partial class Form1 : Form
{static string authority = "https://localhost:5001/";//static string authority = "https://ids2.app1.es/"; //真实环境static string api = $"{authority}WeatherForecast";static string clientId = "Blazor5002";OidcClient _oidcClient;public Form1(){InitializeComponent();string redirectUri = string.Format($"http://localhost/authentication/login-callback");string redirectLogoutUri = string.Format($"http://localhost/authentication/logout-callback");var options = new OidcClientOptions{Authority = authority,ClientId = clientId,RedirectUri = redirectUri,PostLogoutRedirectUri = redirectLogoutUri,Scope = "BlazorWasmIdentity.ServerAPI openid profile",Browser = new WinFormsWebView()};_oidcClient = new OidcClient(options);Login();}private async void Login(){LoginResult loginResult;try{loginResult = await _oidcClient.LoginAsync();}catch (Exception exception){Output.Text = $"Unexpected Error: {exception.Message}";return;}if (loginResult.IsError){MessageBox.Show(this, loginResult.Error, "Login", MessageBoxButtons.OK, MessageBoxIcon.Error);}else{var sb = new StringBuilder(128);foreach (var claim in loginResult.User.Claims){sb.AppendLine($"{claim.Type}: {claim.Value}");}if (!string.IsNullOrWhiteSpace(loginResult.RefreshToken)){sb.AppendLine();sb.AppendLine($"refresh token: {loginResult.RefreshToken}");}if (!string.IsNullOrWhiteSpace(loginResult.IdentityToken)){sb.AppendLine();sb.AppendLine($"identity token: {loginResult.IdentityToken}");}if (!string.IsNullOrWhiteSpace(loginResult.AccessToken)){sb.AppendLine();sb.AppendLine($"access token: {loginResult.AccessToken}");}Output.Text = sb.ToString();}}
}
添加一个类 WinFormsWebView.cs
代码
using IdentityModel.OidcClient.Browser;
using Microsoft.Web.WebView2.WinForms;namespace WinFormsWebView2;public class WinFormsWebView : IBrowser
{private readonly Func<Form> _formFactory;private BrowserOptions? _options;public WinFormsWebView(Func<Form> formFactory){_formFactory = formFactory;}public WinFormsWebView(string title = "Authenticating ...", int width = 1024, int height = 768): this(() => new Form{Name = "WebAuthentication",Text = title,Width = width,Height = height}){ }public async Task<BrowserResult> InvokeAsync(BrowserOptions options, CancellationToken token = default){_options = options;using (var form = _formFactory.Invoke()){using (var webView = new WebView2(){Dock = DockStyle.Fill}){var signal = new SemaphoreSlim(0, 1);var browserResult = new BrowserResult{ResultType = BrowserResultType.UserCancel};form.FormClosed += (o, e) =>{signal.Release();};webView.NavigationStarting += (s, e) =>{if (IsBrowserNavigatingToRedirectUri(new Uri(e.Uri))){e.Cancel = true;browserResult = new BrowserResult(){ResultType = BrowserResultType.Success,Response = new Uri(e.Uri).AbsoluteUri};signal.Release();form.Close();}};try{form.Controls.Add(webView);webView.Show();form.Show();// Initializationawait webView.EnsureCoreWebView2Async(null);// 删除现有的 Cookie,这样以前的登录就不会被记住, 以免影响测试, 反之去掉这行,就可以保持登录//webView.CoreWebView2.CookieManager.DeleteAllCookies();// NavigatewebView.CoreWebView2.Navigate(_options.StartUrl);await signal.WaitAsync();}finally{form.Hide();webView.Hide();}return browserResult;}}}private bool IsBrowserNavigatingToRedirectUri(Uri uri){return uri.AbsoluteUri.StartsWith(_options?.EndUrl);}
}