C# 如何过期/更新存储在Web API SessionToken中的索赔声明

C# 如何过期/更新存储在Web API SessionToken中的索赔声明,c#,asp.net-web-api,claims-based-identity,thinktecture-ident-model,C#,Asp.net Web Api,Claims Based Identity,Thinktecture Ident Model,我正在使用优秀的Thinktecture.IdentityModel库在ASP.NET Web API项目中执行身份验证/授权,该项目将从移动设备和可能的Web客户端使用。我正在使用基本身份验证对访问web api的移动客户端进行身份验证,并使用Thinktecture.IdentityModel提供的内置SessionToken生成。然而,对于如何撤销添加到ClaimSideEntity索赔集合中的索赔,我有一些担心,这些索赔随后(我认为)被编码到提供给客户的SessionToken中 以下是

我正在使用优秀的Thinktecture.IdentityModel库在ASP.NET Web API项目中执行身份验证/授权,该项目将从移动设备和可能的Web客户端使用。我正在使用基本身份验证对访问web api的移动客户端进行身份验证,并使用Thinktecture.IdentityModel提供的内置SessionToken生成。然而,对于如何撤销添加到ClaimSideEntity索赔集合中的索赔,我有一些担心,这些索赔随后(我认为)被编码到提供给客户的SessionToken中

以下是我到目前为止的情况:

根据IdentityModel示例项目中的示例,我创建了以下类

public static class  SecurityConfig
{
  public static void ConfigureGlobal(HttpConfiguration globalConfig)
  {
      globalConfig.MessageHandlers.Add(new AuthenticationHandler(CreateConfiguration()));
  }

  public static AuthenticationConfiguration CreateConfiguration()
  {
      var authentication = new AuthenticationConfiguration()
          {
              ClaimsAuthenticationManager = new MyClaimsTransformer(),
              RequireSsl = false, //TODO:TESTING only
              EnableSessionToken = true,
              SessionToken = new SessionTokenConfiguration()
              {
                  EndpointAddress = "/Authenticate"
              }
          };
       authentication.AddBasicAuthentication(Membership.ValidateUser);

      return authentication;
   }
}
这是从我的Global.asax类调用的

SecurityConfig.ConfigureGlobal(GlobalConfiguration.Configuration);
移动设备从个人收集用户名和密码,并正确设置身份验证标头,并将凭据提供给必要的web端点
http://myhost/api/Authenticate

在服务器上,使用用户名/密码调用my Membership.ValidateUser,如果已验证,则调用
MyClaimsTransformer
的身份验证方法

public class ClaimsTransformer : ClaimsAuthenticationManager
{
   public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
   {
     if (!incomingPrincipal.Identity.IsAuthenticated)
     {
        return base.Authenticate(resourceName, incomingPrincipal);
     }
     return incomingPrincipal;
   }
}
然后,移动客户端接收回令牌,它可以在任何后续请求的认证报头中传递该令牌

这一切都很好

现在我想做的是,在claimtransformer中,添加一些代码,类似于下面的伪代码

var nameClaim = incomingPrincipal.Claims.First(c => c.Type == ClaimTypes.Name);

//Using value in nameClaim lookup roles or permissions for this user.
var someListofRoles = SomeMethodToGetRoles(nameClaim.Value);

//Add user roles to the Claims collection of the ClaimsPrincipal.
foreach(var role in someListOfRoles)
{
   incomingPrincipal.Identities.First().AddClaim(new Claim("Role", role.Name));
}
我希望限制从数据库中请求给定用户的角色或权限列表的次数,并方便在自定义属性中检查这些角色/权限

然而,当我开始添加这个时,我开始考虑这样的场景:一个用户可能已经登录并收到了这个令牌,但是通过系统的另一个用户的某些操作,他们的角色会被更改或撤销。初始用户仍将拥有此令牌,其中包含一个已过期的角色/权限列表,并且在令牌过期之前可以访问任何内容,或者将获得对某些内容的新访问权限,但在他们以某种方式注销之前,不会实际收到该访问权限

是否有一种机制可以使以这种方式创建的SessionToken无效?或者,如果我发现某种方法可以知道用户角色/权限发生了更改,我将如何修改声明并以无缝方式重新发布SessionToken


此外,如何完全撤销SessionToken,即如果我想“注销”一个用户,该如何工作?

数据库更改通知设计完全由您决定。 我建议使用timestamp/rowversion检查数据(用户/角色)是否过时。 您可以将此数据时间戳/行版本存储在服务器上,如用户会话,或客户端的cookie/头。我建议采用前一种方法


如果过时,我建议您只需重新执行CreateConfiguration()方法,该方法应重新创建反映与令牌相关的最新数据更改的所有必要信息。

会话令牌工具没有该功能。我们希望简化“在每个应用程序启动时键入密码”的问题。如果没有完整的数据存储后端(可以在web场等中使用),很难实现撤销


您不应该在会话令牌中存储可能随会话时间而更改的数据

谢谢你的回复。我完全可以通过数据库查找来检测特定用户的角色或权限是否已更新/删除/添加,我们已经在为这些对象添加时间戳。重新执行CreateConfiguration的建议似乎不正确。据我所知,这是一个一次性的“设置”过程,将thinktecture对象连接到我的本地claims transformer和成员身份验证方法。如果我重新执行它,它可能会使每个经过身份验证的用户SessionToken无效,而不仅仅是一个。