写在前面

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)的更多相关文章

  1. 基于 IdentityServer3 实现 OAuth 2.0 授权服务【密码模式(Resource Owner Password Credentials)】

    密码模式(Resource Owner Password Credentials Grant)中,用户向客户端提供自己的用户名和密码.客户端使用这些信息,向"服务商提供商"索要授权 ...

  2. 基于OWIN WebAPI 使用OAuth授权服务【客户端验证授权(Resource Owner Password Credentials Grant)】

    适用范围 前面介绍了Client Credentials Grant ,只适合客户端的模式来使用,不涉及用户相关.而Resource Owner Password Credentials Grant模 ...

  3. 第37章 资源所有者密码验证(Resource Owner Password Validation) - Identity Server 4 中文文档(v1.0.0)

    如果要使用OAuth 2.0资源所有者密码凭据授权(aka password),则需要实现并注册IResourceOwnerPasswordValidator接口: public interface ...

  4. IdentityServer4专题之六:Resource Owner Password Credentials

    实现代码: (1)IdentityServer4授权服务器代码: public static class Config {  public static IEnumerable<Identity ...

  5. asp.net core IdentityServer4 实现 resource owner password credentials(密码凭证)

    前言 OAuth 2.0默认四种授权模式(GrantType) 授权码模式(authorization_code) 简化模式(implicit) 密码模式(resource owner passwor ...

  6. IdentityServer4之Resource Owner Password Credentials(资源拥有者密码凭据许可)

    IdentityServer4之Resource Owner Password Credentials(资源拥有者密码凭据许可) 参考 官方文档:2_resource_owner_passwords ...

  7. IdentityServer4 之 Resource Owner Password Credentials 其实有点尴尬

    前言 接着IdentityServer4的授权模式继续聊,这篇来说说 Resource Owner Password Credentials授权模式,这种模式在实际应用场景中使用的并不多,只怪其太开放 ...

  8. 使用Resource Owner Password Credentials Grant授权发放Token

    对应的应用场景是:为自家的网站开发手机 App(非第三方 App),只需用户在 App 上登录,无需用户对 App 所能访问的数据进行授权. 客户端获取Token: public string Get ...

  9. 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权限认证 ...

随机推荐

  1. Form表单,textarea标签输入框 字数限制,和已输入字数的统计显示

    <script type="text/javascript"> $(document).ready(function() { <%-- 页面进来时就调用 --%& ...

  2. Spring IoC 公共注解详解

    前言 本系列全部基于 Spring 5.2.2.BUILD-SNAPSHOT 版本.因为 Spring 整个体系太过于庞大,所以只会进行关键部分的源码解析. 什么是公共注解?公共注解就是常见的Java ...

  3. java 面向对象(二十二):关键字:final

    final:最终的1.可以用来修饰:类.方法.变量 2.具体的: 2.1 final 用来修饰一个类:此类不能被其他类所继承. * 比如:String类.System类.StringBuffer类 * ...

  4. java 基本语法(十三) 数组(六)数组的常见异常

    1.数组角标越界异常:ArrayIndexOutOfBoundsException int[] arr = new int[]{1,2,3,4,5}; // for(int i = 0;i <= ...

  5. 数据可视化之powerBI入门(三)财务人员必学,使用Powerquery是一种什么体验?

    https://zhuanlan.zhihu.com/p/54700574 财务人员必学,使用Powerquery是一种什么体验? 你和Excel高手的距离只差了一个Power Query!!! 先思 ...

  6. 08 jwt源码剖析

    08 jwt源码剖析 目录 08 jwt源码剖析 1. jwt认证流程 2.jwt创建token 2.1 原理 2.2 jwt校验token 3. jwt使用 4. 源码剖析 总结: JSON Web ...

  7. Java数组倒置

    Java数组之    -- 数组倒置 方法一 :  package mytest; public class test2 { public static void main(String[] args ...

  8. 关于ES6的let和const

    变量 var存在的问题 可以重复声明 无法限制修改 没有块级作用域 (在全局范围内有效) 存在变量提升 const/let 不可以重复声明 let a = 1; let a = 2; var b = ...

  9. Springboot启动扩展点超详细总结,再也不怕面试官问了

    1.背景 Spring的核心思想就是容器,当容器refresh的时候,外部看上去风平浪静,其实内部则是一片惊涛骇浪,汪洋一片.Springboot更是封装了Spring,遵循约定大于配置,加上自动装配 ...

  10. 关于docker--详解安装,常规操作,导入导出等(2017-3-29)

    测试环境 :CentOS 7.1 64位 目的:展示docker的常规使用(安装,常规操作,导入导出等) 其他:关于原理等请参考文章后面的延伸阅读,本文不做深入探讨,且方法不唯一 0x01 关于安装d ...