C# 更改ASP.Net声明后强制进行验证

C# 更改ASP.Net声明后强制进行验证,c#,asp.net,asp.net-mvc,cookies,owin,C#,Asp.net,Asp.net Mvc,Cookies,Owin,我正在用OWIN开发一个ASP.Net应用程序,目前我对声明有一个问题。我有两个应用级别:基础和高级。某些功能仅适用于高级用户。所以我检查声明,如果用户没有声明advanced我返回403。但在这里,我找到了破坏这个系统的解决方法: 用户激活高级模式 他执行任何操作并保存其访问令牌 他禁用了高级模式 现在,他可以像在高级模式下一样使用该令牌执行操作,但实际上他没有这样做的权限 我正试图为这种情况找到一些很好的解决方案,但除了设置1分钟超时或始终检查AspNetUserClaims而不是coo

我正在用OWIN开发一个ASP.Net应用程序,目前我对声明有一个问题。我有两个应用级别:基础和高级。某些功能仅适用于高级用户。所以我检查声明,如果用户没有声明
advanced
我返回403。但在这里,我找到了破坏这个系统的解决方法:

  • 用户激活高级模式
  • 他执行任何操作并保存其访问令牌
  • 他禁用了高级模式
  • 现在,他可以像在高级模式下一样使用该令牌执行操作,但实际上他没有这样做的权限
我正试图为这种情况找到一些很好的解决方案,但除了
设置1分钟超时
始终检查AspNetUserClaims而不是cookie等之外,我没有其他想法,但它们在我的情况下不起作用,因为他可以在这一分钟间隔内激活一个终身功能,然后永远使用它

但我想设置一些服务器端标志,比如
oops,这家伙刚刚更改了他的cookie,从数据库检查它,或者降低常见API调用的数据库往返次数


有没有什么标准的默认方法?或者我选择了一个错误的工具?

您需要根据您的索赔值发送更新cookies

下面是更新您的索赔价值的代码

当用户禁用/启用高级模式,然后更新用户
声明时,在您的操作中

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);
}
一旦您进行了重定向,您将获得get updated索赔值,因此不需要进行数据库往返


不幸的是,我找到的唯一方法实际上是查询数据库本身并检查用户是否具有有效凭据:

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;
    }
}

但保存的请求是什么呢?例如,他刚刚使用chrome功能
另存为cUrl
,然后手动发送请求?它仍然有一个具有此值的cookie。我在下一个请求中删除它,但这并不重要,因为我在服务器端没有检查任何内容。还是我?@AlexZhukovskiy:不,如果你用旧的cookies手动发送请求,它将不起作用。因为旧的cookie值仍然有声明值“1”。@AlexZhukovskiy:cookie令牌的过期时间是多少?目前大约是1天,但这并不重要。正如我上面所说,即使是一分钟的饼干也已经很危险了。@AlexZhukovskiy:我也有过类似的情况,但我的数据并没有那么敏感。这只是我的意见。用户登录后,当用户更改模式,然后在更新声明之前,您将旧cookie值保留在
缓存中
字典中
key=cookie
&
value=current+1day
。现在创建一个
ActionFilter
并检查传入请求的cookie值,如果它存在于
cached
dictionary`中,则阻止该请求。由于您的到期时间为一天,因此您可以从dic中删除值小于当前日期时间的val。在Identity中,您只需注销用户并以编程方式将其重新登录即可。看起来那会让他们的饼干弹起来IPrincipal@Eonasdan我不知道什么时候注销用户。每一个请求?每5分钟?如果是前者,那就没用了。如果用户有5分钟的时间做每件事。“用户激活高级模式”->bounce login->“他禁用高级模式”->bounce login bounce login不会影响已经存在的cookie。如果用户有一个值
val1、val2、val3
并将其发送到服务器,
声明
表示他实际拥有这些值。我无法在服务器端注销这些值。这只是一个请求。简化:服务器接收一些请求,比如说“主页上的弹出消息”和cookie“主页管理器”。在这种情况下,服务器应该做什么?