.net 如何知道 OWIN cookie 何时到期?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23090706/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to know when OWIN cookie will expire?
提问by FrankO
I would like to create some kind of countdown timer based on the time the OWIN cookie will expire. I am using OWIN with MVC 5 and from what I understand SlidingExpiration is on by default. I do not use 'session' as I need this app to live within a web farm (I dont plan on deploying a session database).
我想根据 OWIN cookie 的过期时间创建某种倒数计时器。我将 OWIN 与 MVC 5 一起使用,据我所知,默认情况下 SlidingExpiration 处于启用状态。我不使用“会话”,因为我需要在网络农场中使用此应用程序(我不打算部署会话数据库)。
回答by Phyo
All you need is to get hold of the CookieValidateIdentityContextduring the cookie validation stage. Once you get it, extract whatever you need and keep them as Claimor some other way that you prefer.
您所需要的只是CookieValidateIdentityContext在 cookie 验证阶段掌握。一旦你得到它,提取你需要的任何东西,并Claim以你喜欢的方式或其他方式保留它们。
For MVC 5 with Asp.NET Identity 2.0, you need to perform two steps:
对于带有 Asp.NET Identity 2.0 的 MVC 5,您需要执行两个步骤:
Define custom
OnValidateIdentity, extract cookie information, and keep it asClaim.public class Startup { public void Configuration(IAppBuilder app) { app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, Provider = new CookieAuthenticationProvider { OnValidateIdentity = MyCustomValidateIdentity //refer to the implementation below } } } // this method will be called on every request // it is also one of the few places where you can access unencrypted cookie content as CookieValidateIdentityContext // once you get cookie information you need, keep it as one of the Claims // please ignore the MyUserManager and MyUser classes, they are only for sample, you should have yours private static Task MyCustomValidateIdentity(CookieValidateIdentityContext context) { // validate security stamp for 'sign out everywhere' // here I want to verify the security stamp in every 100 seconds. // but I choose not to regenerate the identity cookie, so I passed in NULL var stampValidator = SecurityStampValidator.OnValidateIdentity<MyUserManager<Myuser>. MyUser>(TimeSpan.FromSeconds(100), null); stampValidator.Invoke(context); // here we get the cookie expiry time var expireUtc = context.Properties.ExpiresUtc; // add the expiry time back to cookie as one of the claims, called 'myExpireUtc' // to ensure that the claim has latest value, we must keep only one claim // otherwise we will be having multiple claims with same type but different values var claimType = "myExpireUtc"; var identity = context.Identity; if(identity.HasClaim(c=> c.Type == claimType)) { var existingClaim = identity.FindFirst(claimType); identity.RemoveClaim(existingClaim); } var newClaim = new Claim(claimType, expireUtc.Value.UtcTicks.ToString()); context.Identity.AddClaim(newClaim); return Task.FromResult(0); } }Access your
Claimin your controller methods// since expiry time has now become part of your claims, you now can get it back easily // this example just returns the remaining time in total seconds, as a string value // assuming this method is part of your controller methods public string RemainingTime() { var identity = User.Identity as ClaimsIdentity; var claimType = "myExpireUtc"; //NOTE: must be the same key value "myExpireUtc" defined in code shown above if(identity != null && identity.HasClaim(c=> c.Type == claimType)) { var expireOn = identity.FindFirstValue(claimType); DateTimeOffset currentUtc = DateTimeOffset.UtcNow; DateTimeOffset? expireUtc = new DateTimeOffset(long.Parse(expireOn), TimeSpan.Zero); var remaining = (expireUtc.Value - currentUtc).TotalSeconds; return remaining.ToString(); } return string.Empty; }
定义 custom
OnValidateIdentity,提取 cookie 信息,并将其保存为Claim.public class Startup { public void Configuration(IAppBuilder app) { app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, Provider = new CookieAuthenticationProvider { OnValidateIdentity = MyCustomValidateIdentity //refer to the implementation below } } } // this method will be called on every request // it is also one of the few places where you can access unencrypted cookie content as CookieValidateIdentityContext // once you get cookie information you need, keep it as one of the Claims // please ignore the MyUserManager and MyUser classes, they are only for sample, you should have yours private static Task MyCustomValidateIdentity(CookieValidateIdentityContext context) { // validate security stamp for 'sign out everywhere' // here I want to verify the security stamp in every 100 seconds. // but I choose not to regenerate the identity cookie, so I passed in NULL var stampValidator = SecurityStampValidator.OnValidateIdentity<MyUserManager<Myuser>. MyUser>(TimeSpan.FromSeconds(100), null); stampValidator.Invoke(context); // here we get the cookie expiry time var expireUtc = context.Properties.ExpiresUtc; // add the expiry time back to cookie as one of the claims, called 'myExpireUtc' // to ensure that the claim has latest value, we must keep only one claim // otherwise we will be having multiple claims with same type but different values var claimType = "myExpireUtc"; var identity = context.Identity; if(identity.HasClaim(c=> c.Type == claimType)) { var existingClaim = identity.FindFirst(claimType); identity.RemoveClaim(existingClaim); } var newClaim = new Claim(claimType, expireUtc.Value.UtcTicks.ToString()); context.Identity.AddClaim(newClaim); return Task.FromResult(0); } }访问您
Claim的控制器方法// since expiry time has now become part of your claims, you now can get it back easily // this example just returns the remaining time in total seconds, as a string value // assuming this method is part of your controller methods public string RemainingTime() { var identity = User.Identity as ClaimsIdentity; var claimType = "myExpireUtc"; //NOTE: must be the same key value "myExpireUtc" defined in code shown above if(identity != null && identity.HasClaim(c=> c.Type == claimType)) { var expireOn = identity.FindFirstValue(claimType); DateTimeOffset currentUtc = DateTimeOffset.UtcNow; DateTimeOffset? expireUtc = new DateTimeOffset(long.Parse(expireOn), TimeSpan.Zero); var remaining = (expireUtc.Value - currentUtc).TotalSeconds; return remaining.ToString(); } return string.Empty; }
I use this approach to remind my application users to extend their session before session time out.
我使用这种方法来提醒我的应用程序用户在会话超时之前延长他们的会话。
Credit to this post How do I access Microsoft.Owin.Security.xyz OnAuthenticated context AddClaims values?
归功于这篇文章如何访问 Microsoft.Owin.Security.xyz OnAuthenticated 上下文 AddClaims 值?
回答by Ricardo Saracino
I just want to build on the first answer, i had problems getting it to work as i was using a custom user store. though the implementation seems simpler for myself
我只想建立在第一个答案的基础上,我在使用自定义用户存储时遇到了问题。虽然实现对我来说似乎更简单
public static class ApplicationCookieValidateIdentityContext
{
public static Task ApplicationValidateIdentity(CookieValidateIdentityContext context)
{
var identity = context.Identity;
if (identity.HasClaim(c => c.Type == "expires"))
{
var existingClaim = identity.FindFirst( "expires");
identity.RemoveClaim(existingClaim);
}
if (context.Properties.ExpiresUtc == null) return Task.FromResult(0);
context.Identity.AddClaim(new Claim("expires", context.Properties.ExpiresUtc.ToString()));
return Task.FromResult(0);
}
}
I also created a filter that adds the expiration to a cookie
我还创建了一个过滤器,将过期时间添加到 cookie
// make sure its defaulted because the claim is not set on the login callback
var expires = DateTimeOffset.Now.AddMinutes(
Convert.ToDouble(ConfigurationManager.AppSettings["SessionTimeInMinutes"]));
if (identity.HasClaim(c => c.Type == "expires"))
{
expires = DateTimeOffset.Parse(identity.FindFirstValue("expires"));
}
cookieHeaderValues.Add(new SessionCookeHeaderValue("expiresAt", expires.ToString("O"), expires));

