更改后强制 ASP.Net 声明验证
Force ASP.Net claims validation after they have been changed
我正在使用 OWIN 开发 ASP.Net 应用程序,目前我遇到了索赔问题。我有两个级别的应用程序:基础和高级。某些功能仅供高级用户使用。所以我检查了索赔,如果用户没有索赔 advanced
我 return 403。但是在这里我找到了破坏这个系统的解决方法:
- 用户激活高级模式
- 他执行任何操作并保存其访问令牌
- 他停用了高级模式
- 现在他可以使用此令牌执行操作,就像他处于高级模式一样,但实际上他没有执行此操作的权限。
我正在尝试为这种情况找到一些好的解决方案,但除了 set 1 minute timeout
或 always check AspNetUserClaims instead of cookie
等我没有其他想法,但它们对我来说不起作用,因为他可以在此一分钟间隔内激活终身功能,然后永远使用它。
但我想设置一些服务器端标志,例如 oops, this guy have just changed his cookies, check it from database
或其他东西,以降低常见 API 调用的数据库往返次数。
有什么标准的默认方法吗?还是我选错了乐器?
您需要根据您的声明价值发送更新cookie。
下面是更新您的声明值的代码。
在用户 disable/enable 高级模式时的操作中,然后更新用户 claims
。
var isAdvanced= "1";
var identity = (ClaimsIdentity)User.Identity;
// check if claim exist or not.
var existingClaim = identity.FindFirst("IsAdvanced");
if (existingClaim != null)
identity.RemoveClaim(existingClaim);
// add/update claim value.
identity.AddClaim(new Claim("IsAdvanced", isAdvanced));
IOwinContext context = Request.GetOwinContext();
var authenticationContext = await context.Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ExternalCookie);
if (authenticationContext != null)
{
authenticationManager.AuthenticationResponseGrant = new AuthenticationResponseGrant(identity,authenticationContext.Properties);
}
一旦您进行重定向,您将获得更新后的声明值,因此您无需进行数据库往返。
Credit to this post.
不幸的是,我发现的唯一方法实际上是查询数据库本身并检查用户是否具有有效凭据:
public bool HasRequiredClaims(string[] requiredClaims)
{
using (var context = new ApplicationDbContext())
{
int actualNumberOfClaims = context.Users
.SelectMany(x => x.Claims)
.Count(c => requiredClaims.Contains(c.ClaimValue)); // claim values are unique per user (in my case) so I don't have to filter on user
return actualNumberOfClaims == claimsValuesToSearch.Length;
}
}
我正在使用 OWIN 开发 ASP.Net 应用程序,目前我遇到了索赔问题。我有两个级别的应用程序:基础和高级。某些功能仅供高级用户使用。所以我检查了索赔,如果用户没有索赔 advanced
我 return 403。但是在这里我找到了破坏这个系统的解决方法:
- 用户激活高级模式
- 他执行任何操作并保存其访问令牌
- 他停用了高级模式
- 现在他可以使用此令牌执行操作,就像他处于高级模式一样,但实际上他没有执行此操作的权限。
我正在尝试为这种情况找到一些好的解决方案,但除了 set 1 minute timeout
或 always check AspNetUserClaims instead of cookie
等我没有其他想法,但它们对我来说不起作用,因为他可以在此一分钟间隔内激活终身功能,然后永远使用它。
但我想设置一些服务器端标志,例如 oops, this guy have just changed his cookies, check it from database
或其他东西,以降低常见 API 调用的数据库往返次数。
有什么标准的默认方法吗?还是我选错了乐器?
您需要根据您的声明价值发送更新cookie。
下面是更新您的声明值的代码。
在用户 disable/enable 高级模式时的操作中,然后更新用户 claims
。
var isAdvanced= "1";
var identity = (ClaimsIdentity)User.Identity;
// check if claim exist or not.
var existingClaim = identity.FindFirst("IsAdvanced");
if (existingClaim != null)
identity.RemoveClaim(existingClaim);
// add/update claim value.
identity.AddClaim(new Claim("IsAdvanced", isAdvanced));
IOwinContext context = Request.GetOwinContext();
var authenticationContext = await context.Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ExternalCookie);
if (authenticationContext != null)
{
authenticationManager.AuthenticationResponseGrant = new AuthenticationResponseGrant(identity,authenticationContext.Properties);
}
一旦您进行重定向,您将获得更新后的声明值,因此您无需进行数据库往返。
Credit to this post.
不幸的是,我发现的唯一方法实际上是查询数据库本身并检查用户是否具有有效凭据:
public bool HasRequiredClaims(string[] requiredClaims)
{
using (var context = new ApplicationDbContext())
{
int actualNumberOfClaims = context.Users
.SelectMany(x => x.Claims)
.Count(c => requiredClaims.Contains(c.ClaimValue)); // claim values are unique per user (in my case) so I don't have to filter on user
return actualNumberOfClaims == claimsValuesToSearch.Length;
}
}