我正在使用优秀的Thinktecture.IdentityModel库在ASP.NET Web API项目中执行身份验证/授权,该项目将从移动设备和Web客户端中使用。我正在使用基本身份验证来验证移动客户端以访问web api,并利用Thinktecture.IdentityModel提供的内置SessionToken生成。但是我对如何撤销添加到ClaimsIdentity声明集合中的声明有一些担忧,然后(我认为)编码到提供给客户端的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
在服务器上,使用用户名/密码调用Membership.ValidatUser,如果验证,则调用MyClaimsTransformer
的Authenticate方法。
public class ClaimsTransformer : ClaimsAuthenticationManager
{
public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
{
if (!incomingPrincipal.Identity.IsAuthenticated)
{
return base.Authenticate(resourceName, incomingPrincipal);
}
return incomingPrincipal;
}
}
移动客户端然后接收一个令牌,它可以在任何后续请求的身份验证头中传递。
这一切都很有效。
现在我想做的是,在ClaimsTransformer中,添加一些代码可以执行类似下面的伪代码。
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));
}
我希望限制从数据库中请求给定用户的角色或权限列表的次数,以及方便在自定义AuthorizeAttribute中检查这些角色/权限。
然而,当我开始添加此内容时,我开始考虑用户已经登录并且会收到此令牌的情况,但是通过系统的其他用户的某些操作,他们的角色将被更改或撤消。初始用户仍然拥有此令牌,其中包含现在已过期的角色/权限列表,并且可以访问任何直到令牌过期的内容,或者可以获得对某些内容的新访问权限,但在他们以某种方式注销之前不会实际接收该访问权限。 / p>
是否存在使以这种方式创建的SessionToken无效的机制?或者,如果我发现某种方式知道对用户角色/权限进行了更改,我将如何修改声明并以无缝方式重新发出SessionToken?
另外,如何完全撤销SessionToken,即如果我想“注销”某个用户,那该怎么办?
答案 0 :(得分:4)
会话令牌工具没有该功能。我们希望简单地解决“在每个应用程序启动时键入密码”问题。如果没有完整的数据存储后端(这可以在网络农场等工作......),很难实现撤销。
您不应在会话令牌中存储可能会话时间更改的数据。
答案 1 :(得分:0)
数据库更改通知设计真的由你决定。 我建议的是使用timestamp / rowversion来检查数据(用户/角色)是否过时。 您可以在服务器上存储此数据时间戳/ rowversion,例如用户会话或客户端的cookie /标头。我推荐前一种方法。
如果过时,我建议您只需重新执行CreateConfiguration()方法,该方法应重新创建反映与令牌相关的最新数据更改的所有必要信息。