Blazor SSR/WASM IDS/OIDC 单点登录授权实例4 - 部署服务端/独立WASM端授权

目录:

  1. OpenID 与 OAuth2 基础知识
  2. Blazor wasm Google 登录
  3. Blazor wasm Gitee 码云登录
  4. Blazor SSR/WASM IDS/OIDC 单点登录授权实例1-建立和配置IDS身份验证服务
  5. Blazor SSR/WASM IDS/OIDC 单点登录授权实例2-登录信息组件wasm
  6. Blazor SSR/WASM IDS/OIDC 单点登录授权实例3-服务端管理组件
  7. Blazor SSR/WASM IDS/OIDC 单点登录授权实例4 - 部署服务端/独立WASM端授权
  8. Blazor SSR/WASM IDS/OIDC 单点登录授权实例5 - Blazor hybird app 端授权
  9. Blazor SSR/WASM IDS/OIDC 单点登录授权实例5 - Winform 端授权

源码

BlazorWasmOIDC

ConsoleOIDC

BlazorOIDC.Server 项目

部署

部署步骤跟平常blazor一样, 这里就不复述了, demo 部署后的域名是 ids2.app.es

新建独立WASM工程

改为以前文章配置的测试点 "applicationUrl": "https://localhost:5002;http://localhost:5003",

Program.cs 文件

using BlazorWasmOIDC;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });var authority = "https://localhost:5001/";
var clientId = "Blazor5002";
var url2 = builder.HostEnvironment.BaseAddress;//完整的配置
builder.Services.AddOidcAuthentication(options =>
{options.ProviderOptions.Authority = authority;options.ProviderOptions.ClientId = clientId;options.ProviderOptions.ResponseType = "code";options.ProviderOptions.RedirectUri = $"{url2}authentication/login-callback";options.ProviderOptions.PostLogoutRedirectUri = $"{url2}authentication/logout-callback";options.ProviderOptions.DefaultScopes.Add("BlazorWasmIdentity.ServerAPI");options.UserOptions.RoleClaim = "role";
});await builder.Build().RunAsync();

Index.razor 文件

@page "/"
@using System.Diagnostics.CodeAnalysis
@using Microsoft.AspNetCore.Components
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication<PageTitle>Index</PageTitle><AuthorizeView><Authorized>你好, @context.User.Identity?.Name</Authorized><NotAuthorized><span>看起来你还没登录</span></NotAuthorized></AuthorizeView>

测试

  1. 先独立启动ssr工程 Blazor SSR/WASM IDS/OIDC 单点登录授权实例1-建立和配置IDS身份验证服务, 监听地址为 https://localhost:5001/

  2. 独立启动 BlazorWasmOIDC 工程, 监听地址为 https://localhost:5002/

  3. 登录测试

[附带]控制台授权测试

添加工程 ConsoleOIDC

<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>Exe</OutputType><TargetFramework>net8.0</TargetFramework><ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable></PropertyGroup> <ItemGroup><FrameworkReference Include="Microsoft.AspNetCore.App"></FrameworkReference><PackageReference Include="Newtonsoft.Json" Version="13.0.3" /><PackageReference Include="Serilog.Extensions.Logging" Version="8.0.0" /><PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" /><PackageReference Include="IdentityModel.OidcClient" Version="5.2.1" /></ItemGroup></Project>

代码

using IdentityModel.Client;
using IdentityModel.OidcClient;
using Newtonsoft.Json.Linq;
using Serilog;namespace ConsoleOIDC;public class Program
{static string authority = "https://localhost:5001/";//static string authority = "https://ids2.app1.es/"; //真实环境static string api = $"{authority}WeatherForecast";static string clientId = "Blazor5002";static OidcClient? _oidcClient;static HttpClient _apiClient = new HttpClient { BaseAddress = new Uri(api) };public static void Main(string[] args) => MainAsync().GetAwaiter().GetResult();public static async Task MainAsync(){Console.WriteLine("+-----------------------+");Console.WriteLine("|  Sign in with OIDC    |");Console.WriteLine("+-----------------------+");Console.WriteLine("");await Login();}private static async Task Login(){// 使用环回地址上的可用端口创建重定向 URI。// 要求 OP 允许 127.0.0.1 上的随机端口 - 否则设置静态端口var browser = new SystemBrowser(5002);var redirectUri = $"http://localhost:{browser.Port}/authentication/login-callback";var redirectLogoutUri = $"http://localhost:{browser.Port}/authentication/logout-callback";var options = new OidcClientOptions{Authority = authority,ClientId = clientId,RedirectUri = redirectUri,PostLogoutRedirectUri = redirectLogoutUri,Scope = "BlazorWasmIdentity.ServerAPI openid profile",//Scope = "Blazor7.ServerAPI openid profile",Browser = browser,Policy = new Policy { RequireIdentityTokenSignature = false }};var serilog = new LoggerConfiguration().MinimumLevel.Error().Enrich.FromLogContext().WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message}{NewLine}{Exception}{NewLine}").CreateLogger();options.LoggerFactory.AddSerilog(serilog);_oidcClient = new OidcClient(options);var result = await _oidcClient.LoginAsync(new LoginRequest());ShowResult(result);await CallApi(result.AccessToken);await NextSteps(result);}private static void ShowResult(LoginResult result, bool showToken = false){if (result.IsError){Console.WriteLine("\n\nError:\n{0}", result.Error);return;}Console.WriteLine("\n\nClaims:");foreach (var claim in result.User.Claims){Console.WriteLine("{0}: {1}", claim.Type, claim.Value);}if (showToken){Console.WriteLine($"\nidentity token: {result.IdentityToken}");Console.WriteLine($"access token:   {result.AccessToken}");Console.WriteLine($"refresh token:  {result?.RefreshToken ?? "none"}");}}private static async Task NextSteps(LoginResult result){var currentAccessToken = result.AccessToken;var currentRefreshToken = result.RefreshToken;var menu = "  x...exit  c...call api   ";if (currentRefreshToken != null) menu += "r...refresh token   ";while (true){Console.WriteLine("\n\n");Console.Write(menu);var key = Console.ReadKey();if (key.Key == ConsoleKey.X) return;if (key.Key == ConsoleKey.C) await CallApi(currentAccessToken);if (key.Key == ConsoleKey.R){var refreshResult = await _oidcClient.RefreshTokenAsync(currentRefreshToken);if (refreshResult.IsError){Console.WriteLine($"Error: {refreshResult.Error}");}else{currentRefreshToken = refreshResult.RefreshToken;currentAccessToken = refreshResult.AccessToken;Console.WriteLine("\n\n");Console.WriteLine($"access token:   {refreshResult.AccessToken}");Console.WriteLine($"refresh token:  {refreshResult?.RefreshToken ?? "none"}");}}}}private static async Task CallApi(string currentAccessToken){try{_apiClient.SetBearerToken(currentAccessToken);var response = await _apiClient.GetAsync("");if (response.IsSuccessStatusCode){var str = await response.Content.ReadAsStringAsync();Console.WriteLine($"Response: {str}");var json = JArray.Parse(await response.Content.ReadAsStringAsync());Console.WriteLine("\n\n");Console.WriteLine(json);}else{Console.WriteLine($"Error: {response.ReasonPhrase}");}}catch (Exception e){Console.WriteLine($"Error: {e.Message}");}}
}

添加 SystemBrowser.cs

using IdentityModel.OidcClient.Browser;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;namespace ConsoleOIDC;public class SystemBrowser : IBrowser
{public int Port { get; }private readonly string _path;public SystemBrowser(int? port = null, string path = null){_path = path;if (!port.HasValue){Port = GetRandomUnusedPort();}else{Port = port.Value;}}private int GetRandomUnusedPort(){var listener = new TcpListener(IPAddress.Loopback, 0);listener.Start();var port = ((IPEndPoint)listener.LocalEndpoint).Port;listener.Stop();return port;}public async Task<BrowserResult> InvokeAsync(BrowserOptions options, CancellationToken cancellationToken = default){using (var listener = new LoopbackHttpListener(Port, _path)){OpenBrowser(options.StartUrl);try{var result = await listener.WaitForCallbackAsync();if (string.IsNullOrWhiteSpace(result)){return new BrowserResult { ResultType = BrowserResultType.UnknownError, Error = "Empty response." };}return new BrowserResult { Response = result, ResultType = BrowserResultType.Success };}catch (TaskCanceledException ex){return new BrowserResult { ResultType = BrowserResultType.Timeout, Error = ex.Message };}catch (Exception ex){return new BrowserResult { ResultType = BrowserResultType.UnknownError, Error = ex.Message };}}}public static void OpenBrowser(string url){try{Process.Start(url);}catch{// hack because of this: https://github.com/dotnet/corefx/issues/10361if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)){url = url.Replace("&", "^&");Process.Start(new ProcessStartInfo("cmd", $"/c start {url}") { CreateNoWindow = true });}else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)){Process.Start("xdg-open", url);}else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)){Process.Start("open", url);}else{throw;}}}
}public class LoopbackHttpListener : IDisposable
{const int DefaultTimeout = 60 * 5; // 5 mins (in seconds)IWebHost _host;TaskCompletionSource<string> _source = new TaskCompletionSource<string>();public string Url { get; }public LoopbackHttpListener(int port, string path = null){path = path ?? string.Empty;if (path.StartsWith("/")) path = path.Substring(1);Url = $"http://localhost:{port}/{path}";_host = new WebHostBuilder().UseKestrel().UseUrls(Url).Configure(Configure).Build();_host.Start();}public void Dispose(){Task.Run(async () =>{await Task.Delay(500);_host.Dispose();});}void Configure(IApplicationBuilder app){app.Run(async ctx =>{if (ctx.Request.Method == "GET"){await SetResultAsync(ctx.Request.QueryString.Value, ctx);}else if (ctx.Request.Method == "POST"){if (!ctx.Request.ContentType.Equals("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase)){ctx.Response.StatusCode = 415;}else{using (var sr = new StreamReader(ctx.Request.Body, Encoding.UTF8)){var body = await sr.ReadToEndAsync();await SetResultAsync(body, ctx);}}}else{ctx.Response.StatusCode = 405;}});}private async Task SetResultAsync(string value, HttpContext ctx){try{ctx.Response.StatusCode = 200;ctx.Response.ContentType = "text/html; charset=utf-8";await ctx.Response.WriteAsync("<h1>您现在可以返回应用程序.</h1>");await ctx.Response.Body.FlushAsync();_source.TrySetResult(value);}catch(Exception ex){Console.WriteLine(ex.ToString());ctx.Response.StatusCode = 400;ctx.Response.ContentType = "text/html; charset=utf-8";await ctx.Response.WriteAsync("<h1>无效的请求.</h1>");await ctx.Response.Body.FlushAsync();}}public Task<string> WaitForCallbackAsync(int timeoutInSeconds = DefaultTimeout){Task.Run(async () =>{await Task.Delay(timeoutInSeconds * 1000);_source.TrySetCanceled();});return _source.Task;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2779428.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

探索现代Web前端开发框架:选择最适合你的工具

在当今快速发展的Web开发领域&#xff0c;前端开发框架的选择显得尤为关键。这些框架可以帮助我们更高效地构建出交互性强、性能卓越的用户界面。本文将带你了解几个当前最受欢迎的Web前端开发框架&#xff0c;并帮助你根据自己的需求选择最合适的工具。 1. React React由Fac…

Linux操作系统基础(七):Linux常见命令(二)

文章目录 Linux常见命令&#xff08;二&#xff09; 一、kill命令 二、ifconfig命令 三、clear命令 四、重启与关机命令 五、which命令 六、hostname命令 七、grep命令 八、|管道 九、useradd命令 十、userdel命令 十一、tar命令 十二、su命令 十三、ps命令 Linu…

【JavaEE】传输层网络协议

传输层网络协议 1. UDP协议 1.1 特点 面向数据报&#xff08;DatagramSocket&#xff09;数据报大小限制为64k全双工不可靠传输有接收缓冲区&#xff0c;无发送缓冲区 UDP的特点&#xff0c;我理解起来就是工人组成的**“人工传送带”**&#xff1a; 面向数据报&#xff08;…

第6章 智能租房——前期准备

学习目标 了解智能租房项目&#xff0c;能够说出项目中各模块包含的功能 熟悉智能租房项目的开发模式与运行机制&#xff0c;能够复述项目的开发模式与运行机制 掌握智能租房项目的创建&#xff0c;能够独立创建智能租房项目 掌握智能租房项目的配置&#xff0c;能够为智能租…

Deepin基本环境查看(九)【被封印的创世神】

文章目录 - 相关文章目录1、概述2、Deepin中的创世神和管理员1&#xff09;创世神root2&#xff09;root被封印原因3&#xff09;其他的神灵【管理员】 3、神殿管理【su与sudo】1&#xff09;su&#xff08;Switch User&#xff09;2&#xff09;sudo&#xff08;Superuser Do&…

2024-2-11-复习作业

1> 要求&#xff1a; 源代码&#xff1a; #include <stdio.h> int fun(int n) {if(n0) return 1;return n*fun(n-1); } int main(int argc, char const *argv[]) {/* code */int n;printf("enter n :");scanf("%d",&n);int sfun(n);printf(…

(已解决)将overleaf上的文章paper上传到arxiv上遇到的问题。

文章目录 前言初级问题后续问题 前言 首先说一点&#xff0c;将paper的pdf文件直接上传arxiv是不行的&#xff0c;arxiv要求我们要上传源文件&#xff0c;所以才这么麻烦。 初级问题 首先上传文件之后有可能会在下面这个界面出现问题&#xff0c;这里一般都比较常见的问题&a…

OpenCV入门:图像处理的基石

在数字图像处理领域&#xff0c;OpenCV&#xff08;开源计算机视觉库&#xff09;是一个不可或缺的工具。它包含了一系列强大的算法和函数&#xff0c;使得开发者可以轻松地处理图像和视频数据。本文将带你走进OpenCV的世界&#xff0c;了解其基本概念和常见应用。 1. OpenCV简…

了解数据治理体系化建模

目录 一、走近数据体系化建模 &#xff08;一&#xff09;软件体系化建模 &#xff08;二&#xff09;数据体系化建模 二、数据体系化建模实践 三、数据管理考量思考 &#xff08;一&#xff09;数据质量方面的考量 &#xff08;二&#xff09;数据安全、合规方面的考量…

机器学习:特征工程笔记

在实践中&#xff0c;收集到的数据往往是不完整、含有噪声和不一致的&#xff0c;这对模型的性能构成挑战&#xff0c;因为其很大程度上依赖于输入数据的质量&#xff0c;因此&#xff0c;特征工程应运而生。特征工程是数据预处理和机器学习的重要环节&#xff0c;包括从原始数…

sheng的学习笔记-docker部署数据库oracle,mysql

部署目录&#xff1a;sheng的学习笔记-部署-目录-CSDN博客 docker基础知识可参考 sheng的学习笔记-docker部署&#xff0c;原理图&#xff0c;命令&#xff0c;用idea设置docker docker安装数据库 mac版本 安装oracle 下载oracle镜像 打开终端&#xff0c;输入 docker s…

服务器被黑,安装Linux RootKit木马

前言 疫情还没有结束&#xff0c;放假只能猫家里继续分析和研究最新的攻击技术和样本了&#xff0c;正好前段时间群里有人说服务器被黑&#xff0c;然后扔了个样本在群里&#xff0c;今天咱就拿这个样本开刀&#xff0c;给大家研究一下这个样本究竟是个啥&#xff0c;顺便也给…

gem5学习(17):ARM功耗建模——ARM Power Modelling

目录 一、Dynamic Power States 二、Power Usage Types 三、MathExprPowerModels 四、Extending an existing simulation 五、Stat dump frequency 六、Common Problems 官网教程&#xff1a;gem5: ARM Power Modelling 通过使用gem5中已记录的各种统计数据&#xff0c;…

Java:字符集、IO流 --黑马笔记

一、字符集 1.1 字符集的来历 我们知道计算机是美国人发明的&#xff0c;由于计算机能够处理的数据只能是0和1组成的二进制数据&#xff0c;为了让计算机能够处理字符&#xff0c;于是美国人就把他们会用到的每一个字符进行了编码&#xff08;所谓编码&#xff0c;就是为一个…

《CSS 简易速速上手小册》第3章:CSS 响应式设计(2024 最新版)

文章目录 3.1 媒体查询基础&#xff1a;网页的智能眼镜3.1.1 基础知识3.1.2 重点案例&#xff1a;适应三种设备的响应式布局3.1.3 拓展案例 1&#xff1a;改变字体大小3.1.4 拓展案例 2&#xff1a;暗模式适配 3.2 响应式图片和视频&#xff1a;让内容自由呼吸3.2.1 基础知识3.…

猫头虎分享已解决Bug | Go Error: cannot use str (type string) as type int in assignment

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

【linux系统体验】-archlinux简易折腾

archlinux 一、系统安装二、系统配置及美化2.1 中文输入法2.2 安装virtualbox增强工具2.3 终端美化2.4 桌面面板美化 三、问题总结3.1 一、系统安装 安装步骤人们已经总结了很多很全: Arch Linux图文安装教程 大体步骤&#xff1a; 磁盘分区安装 Linux内核配置系统&#xff…

git revert回退某次提交

请直接看原文: 【git revert】使用以及理解&#xff08;详解&#xff09;_git revert用法-CSDN博客 -------------------------------------------------------------------------------------------------------------------------------- 前言 试验得知:用Reset HEAD方…

【开源】基于JAVA+Vue+SpringBoot的实验室耗材管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 耗材档案模块2.2 耗材入库模块2.3 耗材出库模块2.4 耗材申请模块2.5 耗材审核模块 三、系统展示四、核心代码4.1 查询耗材品类4.2 查询资产出库清单4.3 资产出库4.4 查询入库单4.5 资产入库 五、免责说明 一、摘要 1.1…

寒假作业:2024/2/11

作业1&#xff1a;使用递归实现n! 代码&#xff1a; #include <stdio.h> #include <string.h> #include <stdlib.h> int fun(int n) {if(0n){return 1;}else{return n*fun(n-1);} } int main(int argc, const char *argv[]) {int n;printf("please en…