点此查看原文
这篇文章是紧接着 Identity Server 4 教程 Part 2: 使用密码保护API 的Identity Server 4系列文章的第三部分。这里涉及到的一些代码,是在上一篇文章的基础之上进行了修改。
我们可以通过IdentityServer4 repository找到官方示例源码,也可以访问我的 github repository来获取我在学习过程中的实践代码。
在本快速入门中,我们将通过OpenID Connect协议添加交互式用户身份验证的界面支持到上一章中构建的IdentityServer中。我们将创建一个将使用IdentityServer进行身份验证的MVC应用程序。
Identity Server已内置OpenID Connect所需的所有协议支持。我们需要为其提供登录,注销等所需的UI部分。
我们可以使用.NET CLI添加界面支持(从src / IdentityServer文件夹中运行):
dotnet new is4ui添加MVC UI后,还需要在DI系统和管道中启用MVC。我们查看Startup.cs时,会在ConfigureServices和Configure方法中找到如何启用MVC的注释。
需要注意的是,如果我们基于ASP.NET Core 3.0来进行开发,那么需要在ConfigureServices中使用services.AddControllersWithViews();,同时在Configure方法中也需进行更改。详细变更可以参见我的代码仓库。
运行IdentityServer项目,我们将看到新添加的界面主页。
接下来需要创建一个MVC客户端项目,并将其配置在5002端口上运行。此外,需要将包含OpenID Connect处理程序的nuget包添加到项目中,以支持使用OpenID Connect身份验证:
dotnet add package Microsoft.AspNetCore.Authentication.OpenIdConnect在Startup的ConfigureServices方法中,注册身份验证支持:
JwtSecurityTokenHandler.DefaultMapInboundClaims = false; services.AddAuthentication(options => { options.DefaultScheme = "Cookies"; options.DefaultChallengeScheme = "oidc"; }) .AddCookie("Cookies") .AddOpenIdConnect("oidc", options => { options.Authority = "http://localhost:5000"; options.RequireHttpsMetadata = false; options.ClientId = "mvc"; options.ClientSecret = "secret"; options.ResponseType = "code"; options.SaveTokens = true; });AddAuthentication将身份验证服务添加到了DI。
我们使用Cookie来本地登录用户(将“Cookies”作为DefaultScheme),并且将DefaultChallengeScheme设置为oidc,因为当处理用户登录时,我们使用的是OpenID Connect协议。
然后,我们使用AddCookie添加可以处理cookies的处理程序。
最后,AddOpenIdConnect用于配置执行OpenID Connect协议的处理程序。Authority指受信任令牌服务的位置。然后,我们通过ClientId和ClientSecret来标明此客户端。SaveTokens用于将IdentityServer中的令牌保留在cookie中(稍后将会使用)。
要确保身份验证服务对每个请求都会执行,在Startup中的Configure添加UseAuthentication:
app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute() .RequireAuthorization(); });RequireAuthorization方法禁用整个应用程序的匿名访问。如果要基于每个控制器或操作方法进行指定,也可以使用[Authorize]特性。
修改主视图以显示用户的声明以及cookie属性:
@using Microsoft.AspNetCore.Authentication <h2>Claims</h2> <dl> @foreach (var claim in User.Claims) { <dt>@claim.Type</dt> <dd>@claim.Value</dd> } </dl> <h2>Properties</h2> <dl> @foreach (var prop in (await Context.AuthenticateAsync()).Properties.Items) { <dt>@prop.Key</dt> <dd>@prop.Value</dd> } </dl>如果现在使用浏览器打开这个项目的页面,将尝试重定向到IdentityServer-这将导致错误,因为尚未注册MVC客户端。
与OAuth 2.0相似,OpenID Connect也使用了“scopes”这个概念。类似的,“scopes”代表我们要保护的内容也就是客户端要访问的内容。与OAuth不同的是,OIDC中的“scopes”不代表API,而是身份数据,例如用户ID,名称或电子邮件地址。
通过修改Config.cs中的Ids属性,添加对标准openid(subject id)和profile(名字,姓氏等)“scopes”的支持:
public static IEnumerable<IdentityResource> Ids => new List<IdentityResource> { new IdentityResources.OpenId(), new IdentityResources.Profile(), };在Startup.cs中向IdentityServer注册身份资源:
var builder = services.AddIdentityServer() .AddInMemoryIdentityResources(Config.Ids) .AddInMemoryApiResources(Config.Apis) .AddInMemoryClients(Config.Clients);示例UI还带有一个内存“用户数据库”。可以通过添加AddTestUsers扩展方法在IdentityServer中启用它:
var builder = services.AddIdentityServer() .AddInMemoryIdentityResources(Config.Ids) .AddInMemoryApiResources(Config.Apis) .AddInMemoryClients(Config.Clients) .AddTestUsers(TestUsers.Users);导航到TestUsers类时,您会看到已定义了两个名为alice和bob的用户以及一些身份声明。我们可以使用这些用户登录。
接下来需要将MVC客户端的新配置项添加到IdentityServer。
基于OpenID Connect的客户端与我们添加的OAuth 2.0客户端非常相似。但是,由于OIDC中的数据传输流始终是交互式的,因此我们需要在配置中添加一些重定向URL。
客户端列表应如下所示:
public static IEnumerable<Client> Clients => new List<Client> { // machine to machine client (from quickstart 1) new Client { ClientId = "client", ClientSecrets = { new Secret("secret".Sha256()) }, AllowedGrantTypes = GrantTypes.ClientCredentials, // scopes that client has access to AllowedScopes = { "api1" } }, // interactive ASP.NET Core MVC client new Client { ClientId = "mvc", ClientSecrets = { new Secret("secret".Sha256()) }, AllowedGrantTypes = GrantTypes.Code, RequireConsent = false, RequirePkce = true, // where to redirect to after login RedirectUris = { "http://localhost:5002/signin-oidc" }, // where to redirect to after logout PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" }, AllowedScopes = new List<string> { IdentityServerConstants.StandardScopes.OpenId, IdentityServerConstants.StandardScopes.Profile } } };导航到受保护的页面将触发身份认证,这时网页应当重定向到IdentityServer上的登录页面。
登录之后,IdentityServer将重定向回MVC客户端,在该客户端上,OpenID Connect身份验证处理程序将处理响应,并通过设置cookie在本地保存登录用户的信息。MVC视图将显示cookie的内容。
最后为MVC客户端用户添加登出功能。
使用IdentityServer之类的身份验证服务,用户登出时仅清除本地应用程序cookie是不够的,还需要与Identity Server通信清除单点登录会话(session)。
确切的协议步骤在OpenID Connect处理程序内部实现,只需将以下代码添加到某个控制器即可触发注销:
public IActionResult Logout() { return SignOut("Cookies", "oidc"); }这将清除本地cookie,然后重定向到IdentityServer。IdentityServer将清除其cookie,然后为用户提供一个链接以返回到MVC应用程序。
Identity Server 4 教程 Part 2: 使用密码保护API
Identity Server 4 教程: Part 4 用户验证和API访问
点此查看原文 原文首发于Chi Blog
Interactive Applications with ASP.NET Core
