34:NET IdentityServer4客户端模式与密码模式

介绍

作用

http://www.identityserver.com.cn/
IdentityServer4 是为ASP.NET Core 系列量身打造的一款基于 OpenID Connect 和 OAuth 2.0 认证框架。
在这里插入图片描述

官网

https://www.identityserver.io/

准备工作

安装模板

安装模板的作用是一会可以自动生成代码。
dotnet new -i IdentityServer4.Templates
在这里插入图片描述

创建项目

输入如下语句,即可创建一个客户端程序。
dotnet new is4aspid -n IdentityServerAspNetIdentity

dotnet new is4empty -n AuthenticationCenterIDS4

项目结构

Config配置使用什么模式进行鉴权授权。
使用dotnet new is4aspid -n IdentityServerAspNetIdentity默认带了客户端模式与code模式,密码模式简单进行下配置即可。
在这里插入图片描述

使用

完成模板创建后,就可以使用了
这里以控制台程序来访问IdentityServer。返回Token后,再带上Toen对受保护的鉴权授权api进行访问

    class Program
    {
        static async Task Main(string[] args)
        {
            //如果要授权
            var client = new HttpClient();
            DiscoveryDocumentResponse disco = await client.GetDiscoveryDocumentAsync("http://localhost:5001/");
            if (disco.IsError)
            {
                Console.WriteLine(disco.Error);
            }

            var accessTokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
            {
                Address = disco.TokenEndpoint,
                ClientId = "m2m.client",
                ClientSecret = "511536EF-F270-4058-80CA-1C89C192F69A",
                Scope = "scope1"
            });

            if (accessTokenResponse.IsError)
            {
                Console.WriteLine(accessTokenResponse.Error);
            }

            var apiclient = new HttpClient();
            apiclient.SetBearerToken(accessTokenResponse.AccessToken);
            var resultResponse = await apiclient.GetAsync("http://localhost:5002/WeatherForecast/Get");

            if (!resultResponse.IsSuccessStatusCode)
            {
                Console.WriteLine(resultResponse.StatusCode);
            }
            else
            {
                var content = await resultResponse.Content.ReadAsStringAsync();
                Console.WriteLine(JArray.Parse(content));
            }
              
            //之前都是postman ;如果需要使用postman,参数如何传递?

            Console.Read();
        }
    }

WebApi受保护的资源

Startup文件中注册服务

			#region 客户端模式
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
           .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
           {
               options.Authority = "http://localhost:5001";
               options.RequireHttpsMetadata = false;
               options.TokenValidationParameters = new TokenValidationParameters
               {
                   ValidateIssuer = true,
                   ValidIssuer = "http://localhost:5001",
                   ValidateAudience = true,
                   ValidAudience = "http://localhost:5001/resources",
                   ValidateIssuerSigningKey = true
               };
           });
            #endregion

引用客户端验证


            #region Identityserver4 
            {
                app.UseAuthentication();
                app.UseAuthorization();
            }
            #endregion

客户端模式

在这里插入图片描述

1>特点描述:

1.客户端模式不代表用户,授权是授权给某一个应用程序客户端;客户端本身就是资源所有者
2.通常用于机器和机器的通信
3.客户端也需要身份验证

2>流程实操:

1.授权,配置密码模式,生成Token;

Startup中的ConfigureServices 方法中添加:

var builder = services.AddIdentityServer(options =>
 {
     // see https://identityserver4.readthedocs.io/en/latest/topics/resources.html
      options.EmitStaticAudienceClaim = true;
  })
     .AddInMemoryIdentityResources(Config.IdentityResources)
     .AddInMemoryApiScopes(Config.ApiScopes)
     .AddInMemoryClients(Config.Clients); 
      builder.AddDeveloperSigningCredential();

支持配置:

 public static class Config
    {
        public static IEnumerable<IdentityResource> IdentityResources =>
             new IdentityResource[]
                   {
                        new IdentityResources.OpenId(), 
                        new IdentityResources.Profile(),
                   }; 
        public static IEnumerable<ApiScope> ApiScopes =>
           new ApiScope[]
            {
                new ApiScope("scope1"),
                new ApiScope("scope2"),
            };

        public static IEnumerable<Client> Clients =>
            new Client[]
            { 
                new Client
                {
                    ClientId = "m2m.client",
                    ClientName = "Client Credentials Client", 
                    AllowedGrantTypes = GrantTypes.ClientCredentials,
                    ClientSecrets = { new Secret("511536EF-F270-4058-80CA-1C89C192F69A".Sha256()) },
                    AllowedScopes = { "scope1" }
                }
            };
    }

2.获取token,Postman访问ids4鉴权中心:http://localhost:5400/connect/token
3.Postman访问Api:带token:http://localhost:5200/api/Third/getlist

3>请求规则:

获取Token:
访问受保护的Api:

密码模式

1>特点描述

1.资源所有的密码凭证(用户名密码),直接用来请求accessToken

2.通常用于遗留的应用

3.资源所有者和客户端之间必须高度信任

4.尽量不用,其他授权方式不可用的时候才使用

2>流程实操

1.IdentityServer 增加Ui,计入AuthenticationCenterIDS4执行命令

dotnet new is4ui

命令执行完毕后,会出现Quickstart、Views 之类的一个MVC界面

2.增加用户: .AddTestUsers(PasswordInitConfig.GetUsers()); 来自于Quickstart文件夹下

Startup中的ConfigureServices 方法中添加:

 services.AddIdentityServer()
 .AddDeveloperSigningCredential()//默认的开发者证书  
 .AddInMemoryIdentityResources(PasswordInitConfig.GetIdentityResourceV4X())//API访问授权资源
 .AddInMemoryClients(PasswordInitConfig.GetClients())  //客户端
 .AddTestUsers(PasswordInitConfig.GetUsers());//添加用户

3.默认TestUser

public class TestUsers
    {
        public static List<TestUser> Users
        {
            get
            {
                var address = new
                {
                    street_address = "One Hacker Way",
                    locality = "Heidelberg",
                    postal_code = 69118,
                    country = "Germany"
                };
                
                return new List<TestUser>
                {
                    new TestUser
                    {
                        SubjectId = "818727",
                        Username = "alice",
                        Password = "alice",
                        Claims =
                        {
                            new Claim(JwtClaimTypes.Name, "Alice Smith"),
                            new Claim(JwtClaimTypes.GivenName, "Alice"),
                            new Claim(JwtClaimTypes.FamilyName, "Smith"),
                            new Claim(JwtClaimTypes.Email, "AliceSmith@email.com"),
                            new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),
                            new Claim(JwtClaimTypes.WebSite, "http://alice.com"),
                            new Claim(JwtClaimTypes.Address, JsonSerializer.Serialize(address), IdentityServerConstants.ClaimValueTypes.Json)
                        }
                    },
                    new TestUser
                    {
                        SubjectId = "88421113",
                        Username = "bob",
                        Password = "bob",
                        Claims =
                        {
                            new Claim(JwtClaimTypes.Name, "Bob Smith"),
                            new Claim(JwtClaimTypes.GivenName, "Bob"),
                            new Claim(JwtClaimTypes.FamilyName, "Smith"),
                            new Claim(JwtClaimTypes.Email, "BobSmith@email.com"),
                            new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),
                            new Claim(JwtClaimTypes.WebSite, "http://bob.com"),
                            new Claim(JwtClaimTypes.Address, JsonSerializer.Serialize(address), IdentityServerConstants.ClaimValueTypes.Json)
                        }
                    }
                };
            }
        }
    }

4.获取Token: 这个是一个Winform程序

private async void RequestaccessTokenBtn_Click(object sender, EventArgs e)
        {
            //如果要授权
            var client = new HttpClient();
           disco = await client.GetDiscoveryDocumentAsync("https://localhost:5001");
            if (disco.IsError)
            {
                MessageBox.Show(disco.Error.ToString());
                return;
            } 
            string userName = this.userNameTxbox.Text;
            string password = this.PassordTxbox.Text; 
            var accessTokneResponse = await client.RequestPasswordTokenAsync(new PasswordTokenRequest()
            {
                Address = disco.TokenEndpoint,
                ClientId = "passwordClientId",
                ClientSecret = "AAAAAAAA-F270-4058-80CA-1C89C192F69A",
                Scope = "scope1 openid", 
                UserName = userName,
                Password = password
            });

            if (accessTokneResponse.IsError)
            {
                MessageBox.Show(accessTokneResponse.Error);
            } 
            this.accessTokenTxBox.Text = accessTokneResponse.AccessToken;
            this.accessToken = accessTokneResponse.AccessToken;
        }

5.请求Api

 private async void RequestApiResource_Click(object sender, EventArgs e)
        {
            HttpClient client = new HttpClient();
            client.SetBearerToken(this.accessToken);
            var apiResourceResponse = await client.GetAsync("http://localhost:5003/WeatherForecast/Get");
            if (!apiResourceResponse.IsSuccessStatusCode)
            {
                Console.WriteLine(apiResourceResponse.StatusCode);
            }
            else
            {
                var content = await apiResourceResponse.Content.ReadAsStringAsync();
                Console.WriteLine(Newtonsoft.Json.Linq.JArray.Parse(content));
                this.apiResourConsole.Text = content;
            }
        }

6.请求userInfo 用户信息

  private async void ReauestIdentityBtn_Click(object sender, EventArgs e)
        { 
            HttpClient client = new HttpClient();
            client.SetBearerToken(this.accessToken);
            var apiResourceResponse = await client.GetAsync(disco.UserInfoEndpoint);
            if (!apiResourceResponse.IsSuccessStatusCode)
            {
                Console.WriteLine(apiResourceResponse.StatusCode);
            }
            else
            {
                var content = await apiResourceResponse.Content.ReadAsStringAsync(); 
                this.IdentityResourceConsole.Text = content;
            }
        }

7.请求更多用户信息

授权层配置:IdentityResources配置:

 public static IEnumerable<IdentityResource> IdentityResources =>
             new IdentityResource[]
                   {
                        new IdentityResources.OpenId(),
                        new IdentityResources.Address(), //更多内容
                        new IdentityResources.Email(), //更多内容
                        new IdentityResources.Phone(),
                        new IdentityResources.Profile(),
                   };

授权层配置:Client配置:

new Client
                {
                    ClientId = "passwordClientId",
                    ClientName = "passwordClientName",

                    AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
                    ClientSecrets = { new Secret("AAAAAAAA-F270-4058-80CA-1C89C192F69A".Sha256()) },

                    AllowedScopes = {
                        "scope1",
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Email,
                        IdentityServerConstants.StandardScopes.Phone,
                        IdentityServerConstants.StandardScopes.Address,
                        IdentityServerConstants.StandardScopes.Profile
                    }
                }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值