IdentityServer4 (2) 密码授权(Resource Owner Password)
写在前面
1、源码(.Net Core 2.2)
git地址:https://github.com/yizhaoxian/CoreIdentityServer4Demo.git
2、相关章节
2.1、《IdentityServer4 (1) 客户端授权模式(Client Credentials)》
2.2、《IdentityServer4 (2) 密码授权(Resource Owner Password)》
2.3、《IdentityServer4 (3) 授权码模式(Authorization Code)》
2.4、《IdentityServer4 (4) 静默刷新(Implicit)》
2.5、《IdentityServer4 (5) 混合模式(Hybrid)》
3、参考资料
IdentityServer4 中文文档 http://www.identityserver.com.cn/
IdentityServer4 英文文档 https://identityserver4.readthedocs.io/en/latest/
4、流程图
此文章是在上一篇文章的基础上继续修改的,基础代码请查看上一篇文章《IdentityServer4(1)客户端授权模式》
密码授权模式,允许一个客户端发送用户名和密码到令牌服务并获得一个表示该用户的访问令牌(AccessToken),这里多了一个概念就是【用户】,账号密码需要用户提供给客户端

一、IdentityServer修改
1、添加一个新的客户端,IdpConfig.GetClients()
new Client
{
// 客户端ID 这个很重要
ClientId = "client pwd",
//资源所有者密码授权客户端定义
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
// 用于认证的密码
ClientSecrets =
{
new Secret("secret".Sha256())
},
// 客户端有权访问的范围(Scopes)
AllowedScopes = {
"api1",
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Address,
IdentityServerConstants.StandardScopes.Email,
IdentityServerConstants.StandardScopes.Phone
}
}
2、添加测试用户
新建一个类 TestUsers.cs
public class TestUsers
{
public static List<TestUser> Users
{
get
{
var address = new
{
street_address = "ChaoYang",
locality = "BeiJing",
postal_code = ,
country = "China"
}; return new List<TestUser>
{
new TestUser
{
SubjectId = "",
Username = "alice",
Password = "alice",
Claims =
{
new Claim(JwtClaimTypes.Name, "TestUser.Alice Smith"),
new Claim(JwtClaimTypes.GivenName, "TestUser.Alice"),
new Claim(JwtClaimTypes.FamilyName, "TestUser.Smith"),
new Claim(JwtClaimTypes.PhoneNumber, "TestUser.13812345678"),
new Claim(JwtClaimTypes.Email, "TestUser.AliceSmith@email.com"),
new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),
new Claim(JwtClaimTypes.WebSite, "TestUser.http://alice.com"),
new Claim(JwtClaimTypes.Address,
JsonConvert.SerializeObject(address), IdentityServerConstants.ClaimValueTypes.Json)
}
},
new TestUser
{
SubjectId = "",
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, JsonConvert.SerializeObject(address), IdentityServerConstants.ClaimValueTypes.Json)
}
}
};
}
}
}
3、注册相关信息
StartUp.cs 添加测试用户和用户认证信息
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentityServer()
.AddDeveloperSigningCredential()
//添加测试用户
.AddTestUsers(TestUsers.Users)
//添加用户认证信息
.AddInMemoryIdentityResources(IdpConfig.GetApiResources())
.AddInMemoryApiResources(IdpConfig.GetApis())
.AddInMemoryClients(IdpConfig.GetClients());
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
二、API修改
1、修改 SuiBianController Get() 返回内容
随意这里改不改无所谓,因为我下面截图,和上一篇对不上 所以在这里说明一下
[HttpGet]
public IActionResult Get()
{
return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
}
三、客户端修改
1、添加一个 Action 请求 AccessToken
public async Task<IActionResult> TokenPwd()
{
var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync(_idpBaseUrl);
if (disco.IsError)
{
return Content("获取发现文档失败。error:" + disco.Error);
} #region 第一种方式请求 token
//var tokenclient = new TokenClient(client, new TokenClientOptions
//{
// ClientId = "client pwd",
// ClientSecret = "secret",
// Address = disco.TokenEndpoint,
//});
//var token = await tokenclient.RequestPasswordTokenAsync("alice", "alice", "api1");
#endregion var token = await client.RequestPasswordTokenAsync(new PasswordTokenRequest
{
Address = disco.TokenEndpoint,
//下面2个属性对应的是 IdentityServer定义的测试用户,这里应是 Action 参数传递进来的,为了方便直接写死的
UserName = "alice",
Password = "alice",
//下面3个属性对应的是 IdentityServer定义的客户端
ClientId = "client pwd",
ClientSecret = "secret",
Scope = "api1 openid profile email phone address"
});
if (token.IsError)
{
return Content("获取 AccessToken 失败。error:" + token.Error);
}
//将token 临时存储到 缓存中
_memoryCache.Set("AccessToken_Pwd", token.AccessToken);
return Content("获取 AccessToken 成功。Token:" + token.AccessToken);
}
2、添加一个Action 测试请求 api1
public async Task<IActionResult> SuiBianPwd()
{
string token, apiurl = GetApiUrl("suibian");
_memoryCache.TryGetValue("AccessToken_Pwd", out token);
if (string.IsNullOrEmpty(token))
{
return Content("token is null");
}
var client = new HttpClient();
client.SetBearerToken(token);
var response = await client.GetAsync(apiurl);
var result = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
_memoryCache.Remove("AccessToken");
return Content($"获取 {apiurl} 失败。StatusCode:{response.StatusCode} \r\n Token:{token} \r\n result:{result}");
}
return Json(JsonConvert.DeserializeObject(result));
}
3、添加一个Action 测试获取用户认证信息
public async Task<IActionResult> IdentityInfoPwd()
{
string token;
_memoryCache.TryGetValue("AccessToken_Pwd", out token);
if (string.IsNullOrEmpty(token))
{
return Content("token is null");
} var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync(_idpBaseUrl);
if (disco.IsError)
{
return Content("获取发现文档失败。error:" + disco.Error);
} client.SetBearerToken(token);
var response = await client.GetAsync(disco.UserInfoEndpoint);
var result = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
_memoryCache.Remove("AccessToken");
return Content($"获取 UserInfo 失败。StatusCode:{response.StatusCode} \r\n Token:{token} \r\n result:{result}");
}
return Json(JsonConvert.DeserializeObject(result));
}
三、客户端测试
1、获取 token
访问 http://localhost:5003/Idp/tokenpwd 获取token成功

2、请求 api1
访问 http://localhost:5003/Idp/suibianpwd 获取api信息成功

3、获取用户认证信息
访问 http://localhost:5003/Idp/identityinfopwd 获取成功

IdentityServer4 (2) 密码授权(Resource Owner Password)的更多相关文章
- 基于 IdentityServer3 实现 OAuth 2.0 授权服务【密码模式(Resource Owner Password Credentials)】
密码模式(Resource Owner Password Credentials Grant)中,用户向客户端提供自己的用户名和密码.客户端使用这些信息,向"服务商提供商"索要授权 ...
- 基于OWIN WebAPI 使用OAuth授权服务【客户端验证授权(Resource Owner Password Credentials Grant)】
适用范围 前面介绍了Client Credentials Grant ,只适合客户端的模式来使用,不涉及用户相关.而Resource Owner Password Credentials Grant模 ...
- 第37章 资源所有者密码验证(Resource Owner Password Validation) - Identity Server 4 中文文档(v1.0.0)
如果要使用OAuth 2.0资源所有者密码凭据授权(aka password),则需要实现并注册IResourceOwnerPasswordValidator接口: public interface ...
- IdentityServer4专题之六:Resource Owner Password Credentials
实现代码: (1)IdentityServer4授权服务器代码: public static class Config { public static IEnumerable<Identity ...
- asp.net core IdentityServer4 实现 resource owner password credentials(密码凭证)
前言 OAuth 2.0默认四种授权模式(GrantType) 授权码模式(authorization_code) 简化模式(implicit) 密码模式(resource owner passwor ...
- IdentityServer4之Resource Owner Password Credentials(资源拥有者密码凭据许可)
IdentityServer4之Resource Owner Password Credentials(资源拥有者密码凭据许可) 参考 官方文档:2_resource_owner_passwords ...
- IdentityServer4 之 Resource Owner Password Credentials 其实有点尴尬
前言 接着IdentityServer4的授权模式继续聊,这篇来说说 Resource Owner Password Credentials授权模式,这种模式在实际应用场景中使用的并不多,只怪其太开放 ...
- 使用Resource Owner Password Credentials Grant授权发放Token
对应的应用场景是:为自家的网站开发手机 App(非第三方 App),只需用户在 App 上登录,无需用户对 App 所能访问的数据进行授权. 客户端获取Token: public string Get ...
- asp.net权限认证:OWIN实现OAuth 2.0 之密码模式(Resource Owner Password Credential)
asp.net权限认证系列 asp.net权限认证:Forms认证 asp.net权限认证:HTTP基本认证(http basic) asp.net权限认证:Windows认证 asp.net权限认证 ...
随机推荐
- MySQL入门(函数、条件、连接)
MySQL入门(四) distinct:去重 mysql>: create table t1( id int, x int, y int ); mysql>: insert into t1 ...
- scala 数据结构(十):折叠、扫描、拉链(合并)、迭代器
1 折叠 fold函数将上一步返回的值作为函数的第一个参数继续传递参与运算,直到list中的所有元素被遍历. 1)可以把reduceLeft看做简化版的foldLeft. 如何理解: def redu ...
- Scala 基础(十):Scala 函数式编程(二)基础(二)过程、惰性函数、异常
1 过程 将函数的返回类型为Unit的函数称之为过程(procedure),如果明确函数没有返回值,那么等号可以省略 注意事项和细节说明 1)注意区分: 如果函数声明时没有返回值类型,但是有 = 号, ...
- 爬虫05 /js加密/js逆向、常用抓包工具、移动端数据爬取
爬虫05 /js加密/js逆向.常用抓包工具.移动端数据爬取 目录 爬虫05 /js加密/js逆向.常用抓包工具.移动端数据爬取 1. js加密.js逆向:案例1 2. js加密.js逆向:案例2 3 ...
- Django之ORM查询操作详解
浏览目录 一般操作 ForeignKey操作 ManyToManyField 聚合查询 分组查询 F查询和Q查询 事务 Django终端打印SQL语句 在Python脚本中调用Django环境 其他操 ...
- linux专题(五):常用的基本命令(三)文件内容查看
http://dwz.date/UDf 概述 Linux系统中使用以下命令来查看文件的内容: cat 由第一行开始显示文件内容 tac 从最后一行开始显示,可以看出 tac 是 cat 的倒着写! n ...
- AI开发利器:HiLens Studio技术解读
摘要:传统的AI应用开发和部署意味着高成本和高门槛,借助HiLens Studio,AI应用开发和部署仅需要三步. 曾几何时, 在我们青春年少时, 当我们看到某篇AI的技术文章时, 心中总不免想要在一 ...
- Linux桌面进化史
自 20 世纪 90 年代初期以来,Linux 桌面也已从简单的窗口管理器发展为成熟.完整的桌面.那么它究竟是如何一步步发展至今的呢?作为从 1993 年就开始使用 Linux 的资深用户,FreeD ...
- go test 测试用例那些事(二) mock
关于go的单元测试,之前有写过一篇帖子go test测试用例那些事,但是没有说go官方的库mock,很有必要单独说一下这个库,和他的实现原理. mock主要的功能是对接口的模拟,需要在写代码的时候定义 ...
- [jvm] -- 垃圾收集算法篇
垃圾收集算法 标记-清除算法 首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象. 缺点: 效率问题: 空间问题(标记清除后会产生大量不连续的碎片) 复制算法 它可以将内存分为大小相同 ...