概述
-
上一个实例 中实现了最简单的 ClientCredential 模式,这种授权模式通常适用于内部后台API简单授权。
-
本实例将实现基于IdentityServer4 实现基于用户名密码的授权模式,这一模式适用于与认证服务属于同一组织(内部)的资源拥有者需要密码认证的场景。
-
本实例将使用一个MVC Web App 作为客户端。
环境和框架
- AspNetCore 3.1
步骤
1. 在AuthServer 服务端添加TestUser和Client
// config类中添加测试用户
public static List<TestUser> GetTestUsers()
{
return new List<TestUser>
{
new TestUser
{
SubjectId="1",
Username="jack",
Password="123456"
},
new TestUser
{
SubjectId="1000",
Username="neil",
Password="123456"
}
};
}
// client集合中添加一个client
new Client {
ClientId="pwdClient",
AllowedGrantTypes=GrantTypes.ResourceOwnerPassword, // resourceowner密码模式
ClientSecrets=new[] {new Secret("654321".Sha256()) },
ClientName="pwdClient",
AllowedScopes={ new ApiScope("api").Name }
},
// startup 注册
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryApiResources(Config.GetApiResources)
.AddInMemoryClients(Config.GetClients)
.AddInMemoryApiScopes(Config.GetApiScopes) // 3.1 新增的坑,不加会报invalid_scope
.AddTestUsers(Config.GetTestUsers()) // 注册testuser
;
3. 调试&测试
3.1 获取token
使用编码方式获取token
var client = new HttpClient();
var disco = client.GetDiscoveryDocumentAsync("http://localhost:5010").Result;
if(disco.IsError)
{
Console.WriteLine(disco.Error);
}
var tokenResponse = client.RequestPasswordTokenAsync( new PasswordTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "pwdClient",
ClientSecret = "654321",
UserName="jack",
Password="123456"
}).Result;
3.2 使用token访问 api 资源。
使用上面获取的token,继续访问之前创建的API资源.
4. 总结
ResourceOwnerPassword 授权模式比较简单,仍然没有涉及到第三方应用应用认证和授权的场景;相比于简单客户端授权,多出了一个User对象,授权场景比客户端粒度细一些。