使用密码保护API

OAuth 2.0 资源所有者密码授权允许一个客户端发送用户名和密码到IdentityServer并获得一个表示该用户的可以用于访问api的Token。

该规范建议仅对“受信任”应用程序使用资源所有者密码授权。 一般来说,当您要验证用户并请求访问令牌时,通常使用交互式OpenID Connect流会更好。

不过,这个授权类型允许我们在IdentityServer 快速入门中引入 用户 的概念,这是我们要展示它的原因。

添加测试用户

就像基于内存存储的资源和客户端一样,对于用户也可以这样做。

IdentityServer 项目中的的Config.cs文件中添加如下代码:

/// <summary>
/// 测试用户信息
/// </summary>
/// <returns></returns>
public static List<TestUser> GetUsers()
{
return new List<TestUser>
{
new TestUser
{
SubjectId = "",
Username = "alice",
Password = "password"
},
new TestUser
{
SubjectId = "",
Username = "bob",
Password = "password"
}
};
}

修改Startup.cs代码如下:

public void ConfigureServices(IServiceCollection services)
{
// 使用内存存储,密钥,客户端和资源来配置身份服务器。
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryApiResources(Config.GetApiResources())//添加api资源
.AddInMemoryClients(Config.GetClients())//添加客户端
.AddTestUsers(Config.GetUsers()); //添加测试用户
}

AddTestUsers扩展方法做了几件事情引擎盖下

  • 增加了对资源所有者密码授权的支持
  • 增加了对登录用户界面通常使用的用户相关服务的支持(我们将在下面使用这些信息)
  • 添加对基于测试用户的配置文件服务的支持(我们将在下面使用这些信息)
为资源所有者密码授予添加一个客户端

您可以通过更改AllowedGrantTypes属性,简单地将授予类型的支持添加到我们现有的客户端 。如果您需要您的客户端能够使用绝对支持的两种授权类型。

通常,您希望为资源所有者用例创建单独的客户端,请将以下内容添加到Config.csGetClients方法中:

/// <summary>
/// 客服端配置
/// </summary>
/// <returns></returns>
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
new Client
{
ClientId = "client",
// 没有交互性用户,使用 clientid/secret 实现认证。
AllowedGrantTypes = GrantTypes.ClientCredentials,
// 用于认证的密码
ClientSecrets =
{
new Secret("secret".Sha256())
},
// 客户端有权访问的范围(Scopes)
AllowedScopes = { "api1" }
},
// resource owner password grant client
new Client
{
ClientId = "ro.client",
//使用用户名密码访问
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedScopes = { "api1" }
}
};
}
使用密码授权请求一个令牌

客户端看起来跟之前客户端证书授权的客户端是相似的。主要差别在于现在的客户端将会以某种方式收集用户密码,然后在令牌请求期间发送到令牌服务。

IdentityModelTokenClient 在这里再次为我们提了供帮助:

//请求令牌
var tokenClient = new TokenClient(disco.TokenEndpoint, "ro.client", "secret");
var tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync("alice", "password", "api1");
if (tokenResponse.IsError)
{
Console.WriteLine(tokenResponse.Error);
return;
}
Console.WriteLine(tokenResponse.Json);
Console.WriteLine("\n\n");

当您将令牌发送给令牌端点时,您会注意到与客户端凭据授权相比有一点小但重要的区别。访问令牌现在将包含sub唯一标识用户的声明。这个“子”声明可以通过在调用API之后检查内容变量来看到,并且也将由控制台应用程序显示在屏幕上。

声明的存在(或不存在)sub使API能够区分代表客户的呼叫和代表用户的调用。

使用OpenID Connect添加用户验证

晓晨Master写的OpenID Connect的详解

OpenID Connect 1.0是OAuth 2.0协议之上的一个简单的身份层。 它允许客户端基于授权服务器执行的身份验证来验证最终用户的身份,以及以可互操作和类似REST的方式获取关于最终用户的基本配置文件信息。

OpenID Connect允许所有类型的客户端(包括基于Web的移动和JavaScript客户端)请求和接收关于认证会话和最终用户的信息。 规范套件是可扩展的,允许参与者使用可选功能,例如身份数据的加密,OpenID提供商的发现和会话管理。

添加UI

OpenID Connect所需的所有协议支持已经内置到IdentityServer中。您需要提供登录,注销,同意和错误所需的UI部分。

虽然每个IdentityServer实现的外观跟工作流程可能总是不同,但我们提供了一个基于MVC的示例UI,您可以使用它作为起始页。

这个用户界面可以在Quickstart UI仓库中找到。下载解压后把QuickstartViewswwwroot这三个文件夹放入您的IdentityServer应用程序。

注:如需使用UI资源,您还需要将MVC添加到主机应用程序中,无论是在DI系统还是管道中。ConfigureServices使用AddMvc扩展方法添加MVC 。

修改Startup.cs中的ConfigureServicesConfigure,完整代码如下:

public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
// 使用内存存储,密钥,客户端和资源来配置身份服务器。
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryApiResources(Config.GetApiResources())//添加api资源
.AddInMemoryClients(Config.GetClients())//添加客户端
.AddTestUsers(Config.GetUsers()); //添加测试用户
//注册mvc服务
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
//添加到HTTP管道中。
app.UseIdentityServer();
//添加静态资源访问
app.UseStaticFiles();
//添加mvc到管道中
app.UseMvcWithDefaultRoute();
}

配置完成后启动项目,访问http://localhost:5000/Account/login,展示如下:

WEB端配置访问控制

接下来,将向web端解决方案添加一个MVC应用程序。使用ASP.NET核心“Web应用程序”(即MVC)模板。不要在向导中配置“身份验证”设置 - 您将在此快速入门中手动执行此操作。创建项目后,将应用程序配置为使用端口5002(有关如何执行此操作的说明,请参阅概述部分)。

要将OpenID Connect身份验证的支持添加到MVC应用程序,请将以下内容添加到Startup.csConfigureServices

public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(); JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = "Cookies"; options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false; options.ClientId = "mvc";
options.SaveTokens = true;
});
}

AddAuthentication将认证服务添加到DI。作为主装置来验证用户(通过我们使用一个cookie "Cookies"DefaultScheme)。我们设置为DefaultChallengeScheme"oidc"因为当我们需要用户登录时,我们将使用OpenID Connect方案。

然后我们使用AddCookie添加可以处理cookie的处理程序。

最后,AddOpenIdConnect用于配置执行OpenID Connect协议的处理程序。在Authority表明我们信任IdentityServer。然后,我们通过身份认证这个客户ClientId。 SignInScheme用于在OpenID Connect协议完成后使用cookie处理程序发出cookie。并SaveTokens用于在cookie中保存来自IdentityServer的令牌(因为它们将在稍后需要)。

另外,我们关闭了JWT声明类型映射,以允许众所周知的声明(例如'sub'和'idp')通过非混淆的声明:

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

然后要确保认证服务执行每个请求,在Startup.cs中加入UseAuthenticationConfigure中:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
} app.UseAuthentication(); app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
}

认证中间件应该在管道中的MVC之前添加。

最后是触发认证握手。为此,转到控制器并添加[Authorize]。还要修改该操作的视图以显示用户的声明,例如:

<dl>
@foreach (var claim in User.Claims)
{
<dt>@claim.Type</dt>
<dd>@claim.Value</dd>
}
</dl>

如果您现在使用浏览器导航到该控制器,将尝试重定向到IdentityServer - 这将导致错误,因为MVC客户端尚未注册。

添加对OpenID Connect Identity Scopes的支持

与OAuth 2.0类似,OpenID Connect也使用范围概念。同样,范围表示您想要保护的以及客户想要访问的内容。与OAuth相比,OIDC中的范围不代表API,而是用户标识,名称或电子邮件地址等身份数据。

通过添加一个新的帮助器来添加对标准openidprofile的范围支持,在Config.cs类中创建一个IdentityResource对象集合:

public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
};
}

注意:所有的标准范围和相应的权利要求都可以在OpenID Connect 规范中找到

然后,您需要将这些身份资源添加到您的IdentityServer中的Startup.cs。将AddInMemoryIdentityResources添加到使用扩展方法AddIdentityServer()中:

public void ConfigureServices(IServiceCollection services)
{
// 使用内存存储,密钥,客户端和资源来配置身份服务器。
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryApiResources(Config.GetApiResources())//添加api资源
.AddInMemoryClients(Config.GetClients())//添加客户端
.AddTestUsers(Config.GetUsers()) //添加测试用户
.AddInMemoryIdentityResources(Config.GetIdentityResources());//添加对OpenID Connect的支持
//注册mvc服务
services.AddMvc();
}

为OpenID Connect隐式流添加客户端

最后是将MVC客户端的新配置条目添加到IdentityServer

基于OpenID Connect的客户端与我们迄今添加的OAuth 2.0客户端非常相似。但是由于OIDC中的流程始终是交互式的,我们需要在配置中添加一些重定向URL。

修改Config.csGetClients代码如下:

public static IEnumerable<Client> GetClients()
{
return new List<Client>
{//定义mvc客服端凭证
new Client
{
ClientId = "mvc",
ClientName = "MVC Client",
AllowedGrantTypes = GrantTypes.Implicit,
//关闭是否返回身份信息界面
RequireConsent=false,
// 登录成功后重定向地址
RedirectUris = { "http://localhost:5002/signin-oidc" }, //注销成功后的重定向地址
PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" }, AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile
}
}
};
}

测试客户端

现在,所有的东西都应该在MVC客户端上。

通过导航到受保护的控制器操作来触发身份验证握手。您应该看到重定向到IdentityServer的登录页面。

成功登录后,用户将看到同意界面。在这里,用户可以决定是否要将他的身份信息发布到客户端应用程序。

注意:可以使用客户端对象上的RequireConsent属性以每个客户端为基础关闭如下界面,这里可以通过修改Config.cs中的GetClients所定义的客服端信息中关闭跳转到该界面。

最后浏览器重定向到客户端应用程序,显示用户的声明

注意:在开发过程中,您有时可能会看到一个异常,说明令牌无法验证。这是因为签名密钥材料是即时创建的,并且只保存在内存中。当客户端和IdentityServer不同步时,会发生此异常。只需在客户端重复操作,下次元数据已经追上,一切都应该正常工作。

添加注销

向MVC客户端添加注销。使用IdentityServer等身份验证服务,仅清除本地应用程序Cookie是不够的。此外,您还需要往身份服务器往返,以清除中央单一登录会话。

确切的协议步骤在OpenID Connect中间件内实现,只需将以下代码添加到某个控制器即可触发注销:

public async Task Logout()
{
await HttpContext.SignOutAsync("Cookies");
await HttpContext.SignOutAsync("oidc");
}

这将清除本地cookie,然后重定向到IdentityServerIdentityServer将清除它的cookie,然后给用户一个链接返回到MVC应用程序。

添加自定义返回身份信息

如上所述,OpenID Connect中间件默认要求配置文件范围。这个范围还包括像名字网站这样的声明

让我们将这些声明添加到用户,以便IdentityServer可以将它们放入身份令牌中,这里我们修改下之前添加的测试用户信息,修改如下:

public static List<TestUser> GetUsers()
{
return new List<TestUser>
{
new TestUser
{
SubjectId = "",
Username = "alice",
Password = "password",
//自定义返回数据
Claims = new []
{
new Claim("name", "Alice"),
new Claim("website", "https://alice.com")
}
},
new TestUser
{
SubjectId = "",
Username = "bob",
Password = "password",
//自定义返回数据
Claims = new []
{
new Claim("name", "Bob"),
new Claim("website", "https://bob.com")
}
}
};
}

下一次进行身份验证时,您的声明页面现在将显示额外的声明信息。

随意添加更多的声明 - 也更多的范围。ScopeOpenID Connect中间件的属性是您配置哪些范围将在身份验证期间发送到IdentityServer的位置。

值得注意的是,检索令牌的索赔是一个可扩展性点IProfileService。由于我们正在使用AddTestUsersTestUserProfileService默认情况下使用。你可以在这里 查看源代码,看看它是如何工作的。

自定义UI(不使用官方UI)

修ConfigureServices如下,自己定义路由地址,一般情况下建议使用官方ui修改。代码如下:

 public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddIdentityServer(options =>
{
//用户交互配置 主要涉及到入口地址参数等
options.UserInteraction = new IdentityServer4.Configuration.UserInteractionOptions
{
LoginUrl = "/Account/Login",
LogoutUrl = "/Account/Logout",
ConsentUrl = "/Account/Consent",
ErrorUrl = "/Account/Error",
LoginReturnUrlParameter = "ReturnUrl",
LogoutIdParameter = "logoutId",
ConsentReturnUrlParameter = "ReturnUrl",
ErrorIdParameter = "errorId",
CustomRedirectReturnUrlParameter = "ReturnUrl",
CookieMessageThreshold =
}; }).AddDeveloperSigningCredential()
.AddInMemoryApiResources(Config.GetApiResources())//添加api资源
.AddInMemoryClients(Config.GetClients());//添加客户端;
}

本章节官方文档地址:点一下

ASP.NET Core的身份认证框架IdentityServer4--(3)令牌服务配置访问控制跟UI添加的更多相关文章

  1. ASP.NET Core的身份认证框架IdentityServer4(7)- 使用客户端证书控制API访问

    前言 今天(2017-9-8,写于9.8,今天才发布)一口气连续把最后几篇IdentityServer4相关理论全部翻译完了,终于可以进入写代码的过程了,比较累.目前官方的文档和Demo以及一些相关组 ...

  2. ASP.NET Core的身份认证框架IdentityServer4(8)- 使用密码认证方式控制API访问

    前言 本文及IdentityServer这个系列使用的都是基于.net core 2.0的.上一篇博文在API项目中我使用了icrosoft.AspNetCore.Authentication.Jwt ...

  3. ASP.NET Core的身份认证框架IdentityServer4(1)-特性一览

    IdentityServer4是ASP.NET Core的一个包含OpenID和OAuth 2.0协议的框架.OpenID和OAuth 的区别请看 https://www.zhihu.com/ques ...

  4. ASP.NET Core的身份认证框架IdentityServer4(9)-使用OpenID Connect添加用户认证

    OpenID Connect OpenID Connect 1.0是OAuth 2.0协议之上的一个简单的身份层. 它允许客户端基于授权服务器执行的身份验证来验证最终用户的身份,以及以可互操作和类似R ...

  5. ASP.NET Core的身份认证框架IdentityServer4(6)- 开始

    安装和概述 启动一个新的IdentityServer项目有两种基本方法: 从头开始 从Visual Studio中的ASP.NET身份模板开始 如果从头开始,我们提供了一些文档.项目帮助和内存存储支持 ...

  6. ASP.NET Core的身份认证框架IdentityServer4(5)- 包和构建

    包和构建 IdentityServer有许多nuget包 IdentityServer4 nuget | github 包含IdentityServer核心对象模型,服务和中间件. 仅支持内存配置和用 ...

  7. ASP.NET Core的身份认证框架IdentityServer4(3)-术语的解释

    IdentityServer4 术语 IdentityServer4的规范.文档和对象模型使用了一些你应该了解的术语. 身份认证服务器(IdentityServer) IdentityServer是一 ...

  8. ASP.NET Core的身份认证框架IdentityServer4(4)- 支持的规范

    IdentityServer实现以下规范: OpenID Connect OpenID Connect Core 1.0 (spec) OpenID Connect Discovery 1.0 (sp ...

  9. ASP.NET Core的身份认证框架IdentityServer4--入门

    ASP.NET Core的身份认证框架IdentityServer4--入门 2018年08月11日 10:09:00 qq_42606051 阅读数 4002   https://blog.csdn ...

随机推荐

  1. Redux

    redux是Flux的一种实现方式,但还是和Flux有些不同. React控制视图层,要想做一个完整的数据流,必须要用react-redux. 官方demo,自己收集了一下: demo1http:// ...

  2. 第二百九十四天 how can I 坚持

    这是怎么了,好难受,晚上都没吃饭,全身都疼.该咋办. 其实,真的是身体最重要. 洗洗睡了.好难受.

  3. SSH2中memcached作为hibernate二级缓存

    一.安装memcached服务端 1. 下载memcached的windows稳定版,解压放某个盘下面,比如在c:\memcached2. 在CMD下输入 "c:\memcached\mem ...

  4. Linux下安装VNC Server

    操作系统centos6.5,在其之上安装vnc server,可利用windows上的vnc client远程登录. 1. 安装 yum install tigervnc-server.x86_64 ...

  5. mongoDB7--游标

    之前我们学习了"增删改查"四中语法和查询表达式的深入学习,我们已经掌握了一定的操作mongodb数据的能力,那么接下来我们就要考虑我们的操作的效率问题了.(1)游标介绍如果我们查询 ...

  6. vue css背景图片打包后路径问题

    limit,代表如果小于大约4k则会自动帮你压缩成base64编码的图片,否则拷贝文件到生产目录 name,后面是打包后的路径: loader,后面 limit 字段代表图片打包限制,这个限制并不是说 ...

  7. JavaScript数组方法--filter、find、findIndex

    继续数组方法,今天应该到filter了. filter:filter() 方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素. 使用: var words = ['spray', 'lim ...

  8. ef join查询

    temp = temp.OrderByDescending(s => s.CreateTime).Skip((param.PageIndex - ) * param.PageSize).Take ...

  9. 读书笔记-iOS核心动画高级技巧

    如果不使用+imageNamed:,那么把整张图片绘制到CGContext可能是最佳的方式了. 这里我们利用了CALayer的KVC来存储和检索任意的值,将图层和索引打标签. 使用KVC打标签

  10. 打包jar问题

    一. 先说一下一般是动态布局最好,效率高,动态就是java写布局,这是 老外的专长,一般res目录是不能打包的,布局动态写,其余的就是图片什么的了,可以建一个assess文件夹,把图片放里面,打jar ...