使用ASP.NET Identity 2.1.0,
我正在尝试添加自定义声明,以便将其添加到往返Cookie中,而不是添加到数据存储区。
声明是针对唯一会话 ID,唯一登录,即使是针对相同的UserId(为了更好地审核每个会话/客户端IP地址所执行的操作)。
到目前为止的尝试是:
Provider = new CookieAuthenticationProvider
{
OnResponseSignIn = (x) =>
{
//Let's pretend this is a Session table Id:
var st = x.Identity.FindFirstValue("ST");
if (string.IsNullOrEmpty(st))
{
//Damn! always needs regeneration because not round-tripping coming back :-(
//Could use Session, but that defeats the purpose of using a cookie...
st = Guid.NewGuid().ToString();
}
x.Identity.AddClaim(new Claim("ST", st));
x.OwinContext.Authentication.SignIn(x.Identity);
},
// Enables the application to validate the security stamp when the user logs in.
// This is a security feature which is used when you change a password or add an external login to your account.
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromSeconds(6),
regenerateIdentity: async (manager, user) =>
{
var x = await user.GenerateUserIdentityAsync(manager);
return x;
}
)
}
});
使用SessionId的缓存(Session / load balanced Shared / etc。),使用UserId作为密钥显然不会起作用(无论ClientIP都会返回相同的SessionId)
使用UserId + ClientIP作为密钥将返回一个SessionId ...但ClientIP明显容易出错,因此等待发生故障。
使用辅助cookie听起来也许它可以工作但是我不愿意为安全系统创建cookie而不了解我将如何减轻这可能带来的每一个劫持问题.......
任何人都有更好的(希望更简单)解决方案吗?
管理将Cookie反序列化为标识的类是什么,然后再返回,检查它是否仍然有效?我可以自定义一个,并在序列化之前在其中添加二级值吗?
感谢您的帮助!
答案 0 :(得分:0)
user.GenerateUserIdentityAsync(manager);
正在向您提出索赔委托人。这是您可以添加自己的声明的理想场所。
或者您可以实施IClaimsIdentityFactory
并将其提交给UserManager.ClaimsIdentityFactory
。但更好的方法是覆盖提供的ClaimsIdentityFactory
并在此之后添加您的声明
我blogged about it a while ago,向下滚动到“添加默认声明”部分。
答案 1 :(得分:0)
我想研究如何完全按照我的意愿生成ASP.NET Identity cookie(包含Identity + Claims,以及我的Session),但直到我明白,这就是我用它做的第二次饼干:
OnResponseSignIn = (x) =>
{
string key = "SessionId";
string serializedSessionId;
var cookie = x.OwinContext.Request.Cookies.SingleOrDefault(y => y.Key == key);
if (!string.IsNullOrEmpty(cookie.Value))
{
var serializedAndEncryptedText = cookie.Value;
serializedSessionId = /*decode*/ serializedAndEncryptedText;
//...maybe update the Session record's last known Activity date?
//and or check that the value contains the SessionId:UserId, and if UserId has changed,
//rebuild a new Session (that's in case Sign out fails to destroy all occurances of it)...
}
else
{
var check = x.OwinContext.Request.Environment;
serializedSessionId = new SessionService().CreateSession(HttpContext.Current.Request.UserHostAddress).ToString(); //pretend that we hit the db...
//TODO: how can we encrypt this value so that it's safer than just ClearText?
string serializedAndEncryptedText = serializedSessionId;
cookie = new KeyValuePair<string, string>(key,serializedAndEncryptedText);
x.Response.Cookies.Append(cookie.Key, cookie.Value);
}
//TODO: what's not good is that we have to remember to destroy the cookie
//every time we sign out...there's risk we don't catch every single occurance of it
//(eg: if the underlying Manager is invoked, rather than the ApplicationManager)
serializedSessionId = cookie.Value;
x.Identity.AddClaim(new Claim(key, serializedSessionId));
x.OwinContext.Authentication.SignIn(x.Identity);
},
然后在单击Login,ExternalLogin或Logout按钮时使用类似于以下内容的方式销毁cookie:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
var sessionIdCookie = this.HttpContext.Request.Cookies["SessionId"];
if (sessionIdCookie != null)
{
sessionIdCookie.Value = string.Empty;
sessionIdCookie.Expires = DateTime.Now.AddYears(-1);
this.HttpContext.Response.Cookies.Add(sessionIdCookie);
}
AuthenticationManager.SignOut();
return RedirectToAction("Index", "Home");
}
sesionservice只不过是我以后为DI优化的以下糟糕的代码:
public class SessionService
{
public Guid CreateSession(string clientIP)
{
Session session =new Session();
session.DateTimeStartedUtc = DateTime.UtcNow;
session.ClientIP = clientIP;
ApplicationDbContext applicationDbContext = new ApplicationDbContext();
applicationDbContext.Set<Session>().Add(session);
applicationDbContext.SaveChanges();
return session.Id;
}
}
所有POC代码都进行了大量清理,但是现在它可以在演示MVC应用程序中运行,其中Cookie很常见。接下来,让它在SPA应用程序中工作(但我必须先了解Bearer令牌的工作原理/方式,然后我才能继续前进)。
如果有人看到上述任何愚蠢的内容,请告诉我......正确的做法对我们来说非常重要(显然,安全和所有...... :-))
感谢。