IdentityServer4 资源所有者密码凭证(Resource Owner Password Credentials)
资源所有者密码凭证(Resource Owner Password Credentials)
资源所有者密码凭证(例如用户名和密码)直接被用来请求Access Token
通常用于遗留的凭证
资源所有者和客户端应用之间必须高度信任
其它授权方式不可用的时候才使用,尽量不用
1.1请求格式
1.2响应格式
1.3请求流程
2.1MainWindow源码
UI

<Window x:Class="WpfClient.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfClient" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="70" /> <RowDefinition Height="40" /> <RowDefinition /> <RowDefinition Height="40" /> <RowDefinition /> <RowDefinition Height="40" /> <RowDefinition Height="70" /> </Grid.RowDefinitions> <StackPanel Grid.Row="0" Margin="20" Orientation="Horizontal"> <Label>用户名:</Label> <TextBox x:Name="UserNameInput" Margin="20 0" Width="150" Height="20">alice</TextBox> <Label>密码:</Label> <PasswordBox x:Name="PasswordInput" Margin="20 0" Width="150" Height="20" Password="alice"></PasswordBox> </StackPanel> <Button Grid.Row="1" Click="RequestAccessToken_ButtonClick"> 1.请求 Access Token </Button> <TextBox Grid.Row="2" x:Name="AccessTokenTextBlock" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" IsReadOnly="True" AcceptsReturn="True" AcceptsTab="True"> </TextBox> <Button Grid.Row="3" Click="RequestScope1Resource_ButtonClick">2.请求 API1资源</Button> <TextBox Grid.Row="4" x:Name="Scope1ResponseTextBlock" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" IsReadOnly="True" AcceptsReturn="True" AcceptsTab="True"> </TextBox> <Button Grid.Row="5" Click="RequestIdentityResource_ButtonClick">3.请求 Identity 资源</Button> <TextBox Grid.Row="6" x:Name="IdentityResponseTextBlock" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" IsReadOnly="True" AcceptsReturn="True" AcceptsTab="True"> </TextBox> </Grid> </Window>
后台

using IdentityModel.Client; using System; using System.Net.Http; using System.Windows; namespace WpfClient { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { private string _accessToken; private DiscoveryDocumentResponse _disco; public MainWindow() { InitializeComponent(); } private async void RequestAccessToken_ButtonClick(object sender, RoutedEventArgs e) { var username = UserNameInput.Text; var password = PasswordInput.Password; // discovery endpoint var client = new HttpClient(); _disco = await client.GetDiscoveryDocumentAsync("https://localhost:5001"); if (_disco.IsError) { Console.WriteLine(_disco.Error); return; } // request access token var tokenResponse = await client.RequestPasswordTokenAsync(new PasswordTokenRequest() { Address = _disco.TokenEndpoint, ClientId = "wpf client", ClientSecret = "wpf secret", Scope = "scope1 openid profile email phone address", UserName = username, Password = password }); if (tokenResponse.IsError) { MessageBox.Show(tokenResponse.Error); return; } _accessToken = tokenResponse.AccessToken; AccessTokenTextBlock.Text = tokenResponse.Json.ToString(); } private async void RequestScope1Resource_ButtonClick(object sender, RoutedEventArgs e) { // call API var apiClient = new HttpClient(); apiClient.SetBearerToken(_accessToken); //var response = await apiClient.GetAsync(disco.UserInfoEndpoint); var response = await apiClient.GetAsync("https://localhost:6001/identity"); if (!response.IsSuccessStatusCode) { MessageBox.Show(response.StatusCode.ToString()); } else { var content = await response.Content.ReadAsStringAsync(); Scope1ResponseTextBlock.Text = content; } } private async void RequestIdentityResource_ButtonClick(object sender, RoutedEventArgs e) { // call Identity Resource from Identity Server var apiClient = new HttpClient(); apiClient.SetBearerToken(_accessToken); var response = await apiClient.GetAsync(_disco.UserInfoEndpoint); if (!response.IsSuccessStatusCode) { MessageBox.Show(response.StatusCode.ToString()); } else { var content = await response.Content.ReadAsStringAsync(); IdentityResponseTextBlock.Text = content; } } } }
在Idp项目中进行配置
3.1IdentityResources配置
找到Config.cs
这里为了可以更多的访问Identity资源,把email phone address 都配置上
3.2Clients配置
这里也需要配置Identity资源
3.3查看测试用户(AddTestUsers)
客户端需要配置用户名密码以及需要访问的Identity资源
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!