基於ASP.NET Core的交互式認證授權
上一篇中已經添加了一個認證授權中心服務,本篇在此前的基礎上進行擴展,通過添加OpenID Connect
協議以支持交互式用戶身份驗證。
本示例代碼中,認證授權中心運行在
http://localhost:5000
下,ASP.NET Core MVC 客戶端網站運行在http://localhost:5002
下
演示效果
訪問:http://localhost:5002/home/authinfo(此站點已配置爲所有頁面都需要授權才能訪問)
如圖,訪問此站點後重定向到認證授權中心:http://localhost:5000。在認證授權中心輸入憑據後,重新返回之前的訪問頁面。
打開開發者工具,可以看到相關cookie已寫入:
服務端配置示例
- 在Config中添加客戶端信息
基於
OpenID Connect
的客戶端與我們添加的OAuth 2.0
客戶端非常相似。但是,由於OIDC
中的流始終是交互式的,因此我們需要在配置中添加一些重定向URL。
public static IEnumerable<Client> Clients => new List<Client>
{
new Client
{
ClientId="mvc",
ClientSecrets={new Secret("secret".Sha256())},
AllowedGrantTypes=GrantTypes.Code,
RequireConsent=false,
RequirePkce=true,
RedirectUris={ "http://localhost:5002/signin-oidc"},
PostLogoutRedirectUris={ "http://localhost:/5002/signout-callback-oidc"},
AllowedScopes=new List<string>{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile
}
}
};
- 在Config中添加對OpenID Connect Identity Scope的支持
與
OAuth 2.0
相似,OpenID Connect
也使用範圍概念。同樣,範圍代表我們要保護的內容以及客戶端要訪問的內容。與OAuth
相比,OIDC
中的範圍不代表API
,而是諸如用戶ID,姓名或電子郵件地址之類的身份數據。
// Defineing Identity Resource
public static IEnumerable<IdentityResource> Ids => new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile()
};
- 添加測試用戶
public class TestUsers
{
public static List<TestUser> Users = new List<TestUser>
{
new TestUser{SubjectId = "818727", Username = "張三", Password = "123456",
Claims =
{
new Claim(JwtClaimTypes.Name, "張三"),
new Claim(JwtClaimTypes.GivenName, "三"),
new Claim(JwtClaimTypes.FamilyName, "張"),
new Claim(JwtClaimTypes.Email, "[email protected]"),
new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),
new Claim(JwtClaimTypes.WebSite, "http://zhangsan.com"),
new Claim(JwtClaimTypes.Address, @"{ '城市': '杭州', '郵政編碼': '310000' }", IdentityServer4.IdentityServerConstants.ClaimValueTypes.Json)
}
}
};
}
- 添加服務到DI
public void ConfigureServices(IServiceCollection services)
{
var builder = services.AddIdentityServer()
.AddInMemoryIdentityResources(Config.Ids)
.AddInMemoryApiResources(Config.Apis)
.AddInMemoryClients(Config.Clients)
.AddTestUsers(TestUsers.Users);
builder.AddDeveloperSigningCredential();
}
創建一個MVC客戶端網站
Install-Package Microsoft.AspNetCore.Authentication.OpenIdConnect -Version 3.1.0
- 添加服務到DI
public void ConfigureServices(IServiceCollection services)
{
// 我們使用cookie來本地登錄用戶(通過“Cookies”作爲DefaultScheme),並且將DefaultChallengeScheme設置爲oidc。因爲當我們需要用戶登錄時,我們將使用OpenID Connect協議。
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
// 添加可以處理cookie的處理程序
.AddCookie("Cookies")
// 用於配置執行OpenID Connect協議的處理程序
.AddOpenIdConnect("oidc", options =>
{
options.Authority = "http://localhost:5000"; // 受信任令牌服務地址
options.RequireHttpsMetadata = false;
options.ClientId = "mvc";
options.ClientSecret = "secret";
options.ResponseType = "code";
options.SaveTokens = true; // 用於將來自IdentityServer的令牌保留在cookie中
});
}
- 確保服務對每個請求執行驗證
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}")
.RequireAuthorization(); // RequireAuthorization方法禁用整個應用程序的匿名訪問
});
}
- 添加控制器方法
public class HomeController : Controller
{
public IActionResult AuthInfo()
{
return View();
}
}
- 添加視圖
@using Microsoft.AspNetCore.Authentication;
<div class="text-left">
<h2>Claims</h2>
<table class="table">
<thead>
<tr>
<th scope="col">Claim Type</th>
<th scope="col">Claim Value</th>
</tr>
</thead>
<tbody>
@foreach (var claim in User.Claims)
{
<tr>
<td>@claim.Type</td>
<td>@claim.Value</td>
</tr>
}
</tbody>
</table>
<h2>Properties</h2>
<table class="table">
<thead>
<tr>
<th scope="col">Claim Type</th>
<th scope="col">Claim Value</th>
</tr>
</thead>
<tbody>
@foreach (var prop in (await Context.AuthenticateAsync()).Properties.Items)
{
<tr>
<td>@prop.Key</td>
<td>@prop.Value</td>
</tr>
}
</tbody>
</table>
</div>