写在前面

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. JQ滚动加载

    $(window).scroll(function () { if ($(document).scrollTop() + $(window).height() >= $(document).he ...

  2. 关于springboot中过滤器和拦截器

    在解决跨域问题中,发现拦截器和过滤器用得不是熟练.就参考了下一下两个作者的文档.希望大家也可以汲取精华 文档1   https://blog.csdn.net/moonpure/article/det ...

  3. Java图片验证码生成工具

    直接把以下代码拷贝使用: import javax.imageio.ImageIO;import java.awt.*;import java.awt.image.BufferedImage;impo ...

  4. IDEA 2020.1 查看内存使用情况

  5. fastjson将json字符串转化为java对象

    目录 一.导入一个fastjson的jar包 二.Json字符串格式 三.根据json的格式创建Java类 四.给java类的所有属性添加setter方法 五.转换为java对象 一.导入一个fast ...

  6. 中介者模式(c++实现)

    中介者模式 目录 中介者模式 模式定义 模式动机 UML类图 源码实现 优点 缺点 模式定义 中介者模式(Mediator),用一个中介对象来封装一系列的对象交互.中介者使各对象不需要显示地相互引用, ...

  7. SpringBoot多数据库连接(mysql+oracle)

    出于业务需求,有时我们需要在spring boot web应用程序中配置多个数据源并连接到多个数据库. 使用过Spring Boot框架的小伙伴们,想必都发现了Spring Boot对JPA提供了非常 ...

  8. DQL_MySQL

    4.DQL(查询数据){SUPER 重点} 4.1DQL (Data Query Language : 数据查询语言) -所有的查询操作: Select 数据库中最核心的语言  create data ...

  9. 一个在raw里面放着数据库文件的网上例子

    https://www.cnblogs.com/yutingliuyl/p/6880103.html

  10. Spring Date JPA实现增删改查

    1.新建一个Cart类 package com.entity; public class Cart { private int id; private int userId; private int ...