本篇基于前文介绍的API访问的控制和用户身份的认证,本篇将在ASP.NET Core应用中把这两者结合起来。
OpenID Connect和OAuth 2.0组合的优点在于,我们可以通过单一协议和与令牌服务的一次交换来实现。
到目前为止,我们仅在令牌请求期间请求标识(身份)资源。当我们在获取令牌后,我们可能需要开始访问一些 API 资源,此时,我们可以让IdentityServer 将返回两个令牌:包含有关身份验证和会话的信息的标识令牌
,以及代表登录的用户访问 API的访问令牌
。
认证授权服务中客户端配置的修改
我们基于前文的认证授权中心服务,修改其客户端配置:
添加了一个AllowedScopes
:CodeSnippets.WebApi
(这个是待会我们MVC客户端要访问的API),以及启用AllowOfflineAccess
一直吃刷新令牌。
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,
"CodeSnippets.WebApi" // 启用对刷新令牌的支持
},
AllowOfflineAccess=true
}
};
MVC网站客户端的修改
添加了两个scope
:CodeSnippets.WebApi
和offline_access
public void ConfigureServices(IServiceCollection services)
{
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中
options.Scope.Add("CodeSnippets.WebApi");
options.Scope.Add("offline_access");
});
}
使用访问令牌
访问API服务
我们只要先获访问令牌,然后把他设置到HttpClient上即可(其中位于GetTokenAsync()
方法Microsoft.AspNetCore.Authentication
命名空间下):
public async Task<IActionResult> CallApi()
{
var accessToken = await HttpContext.GetTokenAsync("access_token");
// var refreshToken =await HttpContext.GetTokenAsync(“ refresh_token”);
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
var content = await client.GetStringAsync("http://localhost:5001/identity");
ViewBag.Json = JArray.Parse(content).ToString();
return View();
}
访问结果如下: