<四>oauth密码模式identity server4实现
前面三篇是实现的客户端模式,这一篇开始实现密码模式,密码模式相对于客户端模式要更加安全一些
在我们上一节中的案例中修改部分代码
1、新增用户配置,identityserver提供了一个测试用户,我们使用他来测试,正式项目是需要到数据库获取的 2、修改identity相关配置。
修改授权服务端config配置
public static class config { public static IEnumerable<ApiScope> GetScopes() { return new ApiScope[] { new ApiScope("api1scope"), new ApiScope("api2scope"), //new ApiScope("scope2"), }; } // 这个 Authorization Server 保护了哪些 API (资源) public static IEnumerable<ApiResource> GetApiResources() { return new[] { new ApiResource("api", "My API") { Scopes = { "api1scope", "api2scope" } } }; } // 哪些客户端 Client(应用) 可以使用这个 Authorization Server public static IEnumerable<Client> GetClients() { return new[] { new Client { ClientId = "myself",//定义客户端 Id ClientSecrets = new [] { new Secret("secret".Sha256()) },//Client用来获取token AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials,//这里使用的是通过用户名密码和ClientCredentials来换取token的方式. ClientCredentials允许Client只使用ClientSecrets来获取token. 这比较适合那种没有用户参与的api动作 AllowedScopes = new [] { "api1scope" }// 允许访问的 API 资源 } }; } public static IEnumerable<TestUser> GetUsers() { return new[] { new TestUser { SubjectId = "1", Username = "myname", Password = "password" } }; } }
修改控制台程序代码
class Program { static void Main(string[] args) { var client = new HttpClient(); var disco = client.GetDiscoveryDocumentAsync("http://localhost:5000").Result; if (disco.IsError) { Console.WriteLine(disco.Error); return; } //var tokenResponse = client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest //{ // Address = disco.TokenEndpoint, // ClientId = "myself", // ClientSecret = "secret", // Scope = "api1scope" //}).Result; var tokenResponse = client.RequestPasswordTokenAsync(new PasswordTokenRequest { Address = disco.TokenEndpoint, UserName = "myname", Password="password", ClientId = "myself", ClientSecret = "secret", Scope = "api1scope" }).Result; if (tokenResponse.IsError) { Console.WriteLine(tokenResponse.Error); return; } Console.WriteLine(tokenResponse.Json); client.SetBearerToken(tokenResponse.AccessToken); var response = client.GetAsync("http://localhost:5001/WeatherForecast").Result; if (!response.IsSuccessStatusCode) { Console.WriteLine(response.StatusCode); } else { var content = response.Content.ReadAsStringAsync().Result; Console.WriteLine(JArray.Parse(content.ToString())); } } }
开启三个项目,console的输出结果: