一.概述

  OAuth 2.0资源(web api)所有者密码授权,允许客户端(Client项目)向令牌服务(IdentityServer项目)发送用户名和密码,并获取代表该用户的访问令牌。在官方文档中讲到:规范通常建议不要使用“资源所有者密码授权”。当用户进行身份验证并请求访问令牌时,使用一个交互式OpenID Connect流程通常要好得多(下篇再了解)。

  本篇介绍“资源所有者密码授权”是因为这种授权允许我们快速启动IdentityServer。开源地址:Github

  下面示例与官方示例有点区别,该示例使用了Identity密码保护API。关于asp.net core Identity的了解实现,查看之前章节或官方文档。示例中分别是IdentityServer令牌项目、 API资源项目、 Client访问项目。与上篇相比一样,还是三个项目,区别在于:

  (1) IdentityServer令牌项目换成了含有asp.net core Identity的MVC项目。

  (2) API资源项目没有变动。

  (3) Client访问项目使用了用户名和密码访问受保护的API。

二. IdentityServer项目

  IdentityServer令牌项目是包含了 Identity功能(安装:Install-Package IdentityServer4),在项目中,添加了Config.cs类和Startup.cs中加入了IdentityServer的启动配置。下面是MVC项目目录结构:

  (1) 添加用户

    IdentityServer类库中自带TestUser测试类,是DTO数据传输对象,存储用户及其声明(claims)。TestUser是用于测试中的内存(In-memory)用户对象。在正式环境下,获取数据库中的用户表(User),需要结合IdentityServer的IResourceOwnerPasswordValidator接口(不再本篇讲述中)。 下面通过在config.cs类中添加GetUsers方法获取用户密码,存储在TestUser数据传输对象中。

        /// <summary>
///获取用户,这些用户可以访问受密码保护的API
/// </summary>
/// <param name="provider"></param>
/// <returns></returns>
public static List<TestUser> GetUsers(ServiceProvider provider)
{
var webAppIdentityDemoUser = provider.GetRequiredService<UserManager<WebAppIdentityDemoUser>>();
IList<WebAppIdentityDemoUser> users = null;
//获取Identity的User表用户,条件是属于Administrator角色的用户
users = webAppIdentityDemoUser.GetUsersInRoleAsync("Administrator").Result; List<TestUser> testUserList = new List<TestUser>();
foreach (WebAppIdentityDemoUser user in users)
{
testUserList.Add(new TestUser() { SubjectId = user.Id.ToString(), Username = user.UserName, Password = user.PasswordHash });
}
return testUserList;
}

  (2) 然后在Startup类的ConfigureServices方法中使用IdentityServer注入测试用户:

            ServiceProvider provider = services.BuildServiceProvider();

            var builder = services.AddIdentityServer()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApis())
.AddInMemoryClients(Config.GetClients())
.AddTestUsers(Config.GetUsers(provider));

  (3) 定义客户端, 使用密码授予访问此API(资源范围:api1)

    在config.cs类中,定义客户端,通过修改AllowedGrantTypes枚举来简单地向现有客户端添加对授权类型的支持, 将以下代码添加到客户端配置中, 里面支持二个Client授权类型,分别是ClientCredentials使用凭证来访问令牌和ResourceOwnerPassword 使用密码来访问令牌。

      public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
new Client
{
ClientId = "client", // no interactive user, use the clientid/secret for authentication
AllowedGrantTypes = GrantTypes.ClientCredentials, // secret for authentication
ClientSecrets =
{
new Secret("secret".Sha256())
}, // scopes that client has access to
AllowedScopes = { "api1" }
},
// resource owner password grant client
new Client
{
ClientId = "ro.client",
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword, ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedScopes = { "api1" }
}
};
}

  

三.Client项目

  该Client项目类似于上篇介绍的Client项目,该项目名为ResourceOwnerClient, 该Client将收集用户名和密码,并在令牌请求期间,将其发送到IdentityServer令牌服务(WebAppIdentityDemo项目)

            // request token 请求令牌
var tokenResponse = await client.RequestPasswordTokenAsync(new PasswordTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "ro.client",
ClientSecret = "secret", UserName = "924964690@qq.com",
Password = "AQAAAAEAACcQAAAAEH4Xhui5BByq6d8VS5Z+S2o2SnlkyrP5pN9CmMpgJ4QiIVrt7lBLzDlEWa6AdlpxpA==",
Scope = "api1"
}); if (tokenResponse.IsError)
{
Console.WriteLine(tokenResponse.Error);
return;
} Console.WriteLine(tokenResponse.Json);
Console.WriteLine("\n\n");

  最后测试,先启动WebAppIdentityDemo项目程序,再启动API程序,最后启动Client客户端来访问API,通过下图可以了解到:(1)客户端请求使用“用户名和和密码”访问令牌(token)成功, (2) 客户端使用令牌(AccessToken)来访问受密码保护的web API接口成功。

  

  

  参考文献

    使用密码保护API

    

asp.net core系列 55 IS4使用Identity密码保护API的更多相关文章

  1. asp.net core系列 55 IS4结合Identity密码保护API

    一.概述 OAuth 2.资源所有者密码授权允许客户端(Client项目)向令牌服务(IdentityServer项目)发送用户名和密码,并获取代表该用户的访问令牌.本篇将IS4结合asp.net c ...

  2. 【asp.net core 系列】15 自定义Identity

    0. 前言 在之前的文章中简单介绍了一下asp.net core中的Identity,这篇文章将继续针对Identity进行进一步的展开. 1. 给Identity添加额外的信息 在<[asp. ...

  3. asp.net core系列 54 IS4用客户端凭据保护API

    一. 概述 本篇开始进入IS4实战学习,从第一个示例开始,该示例是 “使用客户端凭据保护API”,这是使用IdentityServer保护api的最基本场景.该示例涉及到三个项目包括:Identity ...

  4. asp.net core系列 58 IS4 基于浏览器的JavaScript客户端应用程序

    一. 概述 本篇探讨使用"基于浏览器的JavaScript客户端应用程序".与上篇实现功能一样,只不过这篇使用JavaScript作为客户端程序,而非core mvc的后台代码Ht ...

  5. asp.net core系列 57 IS4 使用混合流(OIDC+OAuth2.0)添加API访问

    一.概述 在上篇中,探讨了交互式用户身份验证,使用的是OIDC协议. 在之前篇中对API访问使用的是OAuth2.0协议.这篇把这两个部分放在一起,OpenID Connect和OAuth 2.0组合 ...

  6. asp.net core系列 56 IS4使用OpenID Connect添加用户认证

    一.概述 在前二篇中讲到了客户端授权的二种方式: GrantTypes.ClientCredentials凭据授权和GrantTypes.ResourceOwnerPassword密码授权,都是OAu ...

  7. 【目录】asp.net core系列篇

    随笔分类 - asp.net core系列篇 asp.net core系列 68 Filter管道过滤器 摘要: 一.概述 本篇详细了解一下asp.net core filters,filter叫&q ...

  8. asp.net core系列 30 EF管理数据库架构--必备知识 迁移

    一.管理数据库架构概述 EF Core 提供两种主要方法来保持 EF Core 模型和数据库架构同步.一是以 EF Core 模型为基准,二是以数据库为基准. (1)如果希望以 EF Core 模型为 ...

  9. WPF中的常用布局 栈的实现 一个关于素数的神奇性质 C# defualt关键字默认值用法 接口通俗理解 C# Json序列化和反序列化 ASP.NET CORE系列【五】webapi整理以及RESTful风格化

    WPF中的常用布局   一 写在开头1.1 写在开头微软是一家伟大的公司.评价一门技术的好坏得看具体的需求,没有哪门技术是面面俱到地好,应该抛弃对微软和微软的技术的偏见. 1.2 本文内容本文主要内容 ...

随机推荐

  1. Apriori算法思想和其python实现

    第十一章 使用Apriori算法进行关联分析 一.导语 "啤酒和尿布"问题属于经典的关联分析.在零售业,医药业等我们经常需要是要关联分析.我们之所以要使用关联分析,其目的是为了从大 ...

  2. NGINX按天生成日志文件的简易配置

    NGINX按天生成日志文件的简易配置 0x01 最近后端童鞋遇到一个小需求,拆分nginx生成的log文件,最好是按天生成,看着她还有很多bug待改的状态,我说这个简单啊,我来吧.曾经搞node后端的 ...

  3. 谈谈书本《c#物联网程序设计基础》中的技术瑕疵,如果你将要读本书,请进来看看!

    今天去书店看到一本名为<c#物联网程序设计基础>的书,对物联网感兴趣的我抓起来就看,书中的项目都是上位机开发项目,较简单,如果物联网开发只是这样,看起来我做物联网开发也是绰绰有余.这边书我 ...

  4. Python《学习手册:第二章-习题》

    什么是Python解释器? Python解释器是运行Python程序的程序. 什么是源代码? 源代码是为程序所写的语句:它包括文本文件(通常以.py为文件名结尾)的文件. 什么是字节码? 字节码是Py ...

  5. 强大的测试管理工具---TestTrack Pro

    我的一篇老文章了,当年可能是第一篇介绍.从CSDN搬来的. 版权声明:本文为博主原创文章,未经博主允许不得转载. 强大的测试管理工具---TestTrack Pro 时间:2004-03-09 简介: ...

  6. dmraid 用法

    dmraid 全名为设备对应器磁盘阵列(Device Mapper RAID),利用Linux内核提供的设备对应器(Device Mapper)机制 ,为多种磁盘阵列设备提供磁盘阵列的设备文件,让用户 ...

  7. shell 中的for、while循环及if语句

    shell与其他语言一样也支持for.while循环 for循环的一般格式如下: #!/bin/sh for 变量 in 列表 do command command command ......... ...

  8. ehcache与redis的比较与应用场景分析(转)

    ehcache直接在jvm虚拟机中缓存,速度快,效率高:但是缓存共享麻烦,集群分布式应用不方便.redis是通过socket访问到缓存服务,效率比ecache低,比数据库要快很多,处理集群和分布式缓存 ...

  9. Mysql:查询每个月下的数据,根据状态或者年份的sql语句

     ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 本次的MySQL开篇记录了一道面试题,我给其扩展一下 这面试题它难点在什么地方,不外乎是操作月份和将其展示的 ...

  10. tkinter中spinbox递增和递减控件(十)

    spinbox递增和递减控件 import tkinter wuya = tkinter.Tk() wuya.title("wuya") wuya.geometry("3 ...