我使用带有asp .net标识的.net作为身份验证点。我的API/WebApps调用身份服务器来获取访问令牌。
现在,如何在我的api/app控制器中授权在某些操作之前或内部操作之前使用?
我可以添加角色来访问令牌,然后在控制器中(在web /web应用程序中)使用AuthorizeAttribute并检查用户是否IsInRole。
但这意味着,如果我要更改用户角色,他将在登录后看到它(因为角色是访问令牌的一部分)或令牌必须过期。
每次需要授权他执行某些操作(特别是修改/删除某些数据等操作)时,我都想询问身份服务器有关用户角色的信息。
怎么问?或者我要找什么?
发布于 2017-05-12 07:41:00
所以这里有几个可能的解决方案:
就实现难度而言,降低cookie生存期是最简单的(只更改cookie过期),但它不能保证最新的声明,而且对用户来说是可见的(频繁重定向到IdentityServer,但如果访问令牌生存期仍然有效,则不需要登录)。
让webapp在每个请求上调用UserInfo端点是下一个最简单的方法(参见下面的示例),但性能影响最差。每个请求都将产生到IdentityServer的往返。
端点/订阅服务器模型的性能开销最低。只有当用户配置文件信息实际更改时,才会发生UserInfo对IdentityServer的请求。这一点要执行起来要复杂一些:
码样本
在每次调用时从端点获取更新的UserInfo
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationScheme = "NameOfYourCookieAuthSchemeHere",
Events = new CookieAuthenticationEvents()
{
OnValidatePrincipal = async context =>
{
// Get updated UserInfo from IdentityServer
var accessToken = context.Principal.Claims.FirstOrDefault(c => c.Type == "access_token").Value;
var userInfoClient = new UserInfoClient("https://{IdentityServerUrlGoesHere}");
var userInfoResponse = await userInfoClient.GetAsync(accessToken);
// Invalidate Principal if Error Response
if (userInfoResponse.IsError)
{
context.RejectPrincipal();
await context.HttpContext.Authentication.SignOutAsync("NameOfYourCookieAuthSchemeHere");
}
else
{
// Check if claims changed
var claimsChanged = userInfoResponse.Claims.Except(context.Principal.Claims).Any();
if (claimsChanged)
{
// Update claims and replace principal
var newIdentity = context.Principal.Identity as ClaimsIdentity;
newIdentity.AddClaims(userInfoResponse.Claims);
var updatedPrincipal = new ClaimsPrincipal();
context.ReplacePrincipal(updatedPrincipal);
context.ShouldRenew = true;
}
}
}
}
});更新来自IdentityServer的订阅更改消息。这个例子假设您已经创建了一个服务(例如IUserChangedService),它存储从IdentityServer接收到的端点上的userIds。我没有webapp接收端点或服务的示例。
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationScheme = "NameOfYourCookieAuthSchemeHere",
Events = new CookieAuthenticationEvents()
{
OnValidatePrincipal = async context =>
{
// Get User ID
var userId = context.Principal.Claims.FirstOrDefault(c => c.Type == "UserIdClaimTypeHere");
var userChangedService = context.HttpContext.RequestServices.GetRequiredService<IUserChangedService>();
var userChanged = await userChangedService.HasUserChanged(userId);
if (userChanged)
{
// Make call to UserInfoEndpoint and update ClaimsPrincipal here. See example above for details
}
}
}
});除了使用本地数据库之外,asp.net核心文档也有这方面的示例。连接到OnValidatePrincipal方法的方法是相同的:https://learn.microsoft.com/en-us/aspnet/core/security/authentication/cookie#reacting-to-back-end-changes
希望这能有所帮助!
https://stackoverflow.com/questions/43913286
复制相似问题