每次请求时,ASP.NET身份重新生成身份
作者:互联网
我有一个ASP.NET MVC应用程序,正在使用ASP.NET Identity2.我有一个奇怪的问题.浏览器向我的网站发出的每个请求都会调用ApplicationUser.GenerateUserIdentityAsync.我添加了一些Trace.WriteLine,这是删除IIS输出后的结果:
IdentityConfig.Configuration called
ApplicationUser.GenerateUserIdentityAsync called url: http://localhost:54294/
ApplicationUser.GenerateUserIdentityAsync called url: http://localhost:54294/Content/bootstrap.css
ApplicationUser.GenerateUserIdentityAsync called url: http://localhost:54294/Scripts/modernizr-2.8.3.js
ApplicationUser.GenerateUserIdentityAsync called url: http://localhost:54294/Content/site.css
ApplicationUser.GenerateUserIdentityAsync called url: http://localhost:54294/Scripts/jquery-2.1.3.js
ApplicationUser.GenerateUserIdentityAsync called url: http://localhost:54294/Scripts/bootstrap.js
ApplicationUser.GenerateUserIdentityAsync called url: http://localhost:54294/Scripts/respond.js
ApplicationUser.GenerateUserIdentityAsync called url: http://localhost:54294/Scripts/script.js
ApplicationUser.GenerateUserIdentityAsync called url: http://localhost:54294/Glimpse.axd?n=glimpse_client&hash=8913cd7e
ApplicationUser.GenerateUserIdentityAsync called url: http://localhost:54294/Glimpse.axd?n=glimpse_metadata&hash=8913cd7e&callback=glimpse.data.initMetadata
ApplicationUser.GenerateUserIdentityAsync called url: http://localhost:54294/Glimpse.axd?n=glimpse_request&requestId=6171c2b0-b6e5-4495-b495-4fdaddbe6e8f&hash=8913cd7e&callback=glimpse.data.initData
ApplicationUser.GenerateUserIdentityAsync called url: http://localhost:54294/Glimpse.axd?n=glimpse_sprite&hash=8913cd7e
ApplicationUser.GenerateUserIdentityAsync called url: http://localhost:54294/__browserLink/requestData/38254292a54f4595ad26158540adbb6a?version=2
而如果我运行由模板创建的默认MVC应用程序,则会得到以下信息:
IdentityConfig.Configuration called
并且只有在我登录后,它将调用ApplicationUser.GenerateUserIdentityAsync.
我到处都看过我以为可能会看到的东西,但没有发现任何结果.我正在使用(如果有帮助)
StructureMap 3
Elmah
Glimpse
ASP.NET MVC 5
EF6
ASP.NET Identity 2
附加信息
我将用户直接添加到数据库中,而无需使用UserManage.我不确定它是否会对Identity造成任何问题.
更新资料
我删除了数据库,但此事不再发生.怎么了?
更新2
它发生在我的Google Chrome浏览器中(我使用浏览器监视SQL连接),并且删除了存储的Cookie后,并没有发生.可以在其他浏览器中登录导致此问题吗?
更新3
也注销-登录似乎可以暂时解决问题.
解决方法:
我遇到了同样的问题,在研究了源代码和一些侦探性工作之后,我找到了解决方案.问题出在SecurityStampValidator内部,它用作默认的OnValidateIdentity处理程序.请参见源代码here.有趣的部分:
var issuedUtc = context.Properties.IssuedUtc;
// Only validate if enough time has elapsed
var validate = (issuedUtc == null);
if (issuedUtc != null)
{
var timeElapsed = currentUtc.Subtract(issuedUtc.Value);
validate = timeElapsed > validateInterval;
}
此部分针对每个请求运行,如果validate为true,则将调用getUserIdCallback和regenerateIdentityCallback(在跟踪输出中可见).这里的问题是,issuedUtc始终是创建cookie的日期,因此,经过validateInterval后,validate始终为true.这解释了您所经历的怪异行为.如果validateInterval为10分钟,则在创建cookie之后(在部署应用程序,清除cookie,注销和再次登录时cookie重置之后),将在10分钟或更长时间内为每个请求运行验证逻辑.
SecurityStampValidator应该根据先前的验证日期(或第一次检查时的发布日期)做出是否验证的决定,但事实并非如此.为使IssuedUtc日期向前发展,有3种可能的解决方案:
>在每个validateInterval中重置cookie,这意味着SingOut和SignIn.类似的解决方案here.这似乎是一项昂贵的操作,尤其是在validateInterval设置为仅几分钟的情况下.
>利用CookieAuthenticationOptions.SlidingExpiration逻辑使Cookie自动重新发出.在this post中解释得很好.
If SlidingExpiration is set to true then the cookie would be re-issued on any request half way through the ExpireTimeSpan. For example, if the user logged in and then made a second request 16 minutes later the cookie would be re-issued for another 30 minutes. If the user logged in and then made a second request 31 minutes later then the user would be prompted to log in.
对于我的情况(Intranet应用程序),不活动30分钟后注销的用户是不可接受的.我需要具有默认的ExpireTimeSpan,即14天.因此,这里的选择是实施某种ajax轮询以延长cookie寿命.听起来要完成此相当简单的方案需要付出很多努力.
>我最后选择使用的最后一个选项是修改SecurityStampValidator实现以具有滑动验证方法.下面的示例代码.请记住在Startup.Auth.cs中用SlidingSecurityStampValidator替换SecurityStampValidator.我将IdentityValidationDates字典添加到原始实现中以存储每个用户的验证日期,然后在检查是否需要验证时使用它.
public static class SlidingSecurityStampValidator
{
private static readonly IDictionary<string, DateTimeOffset> IdentityValidationDates = new Dictionary<string, DateTimeOffset>();
public static Func<CookieValidateIdentityContext, Task> OnValidateIdentity<TManager, TUser, TKey>(
TimeSpan validateInterval, Func<TManager, TUser, Task<ClaimsIdentity>> regenerateIdentityCallback,
Func<ClaimsIdentity, TKey> getUserIdCallback)
where TManager : UserManager<TUser, TKey>
where TUser : class, IUser<TKey>
where TKey : IEquatable<TKey>
{
if (getUserIdCallback == null)
{
throw new ArgumentNullException(nameof(getUserIdCallback));
}
return async context =>
{
var currentUtc = DateTimeOffset.UtcNow;
if (context.Options != null && context.Options.SystemClock != null)
{
currentUtc = context.Options.SystemClock.UtcNow;
}
var issuedUtc = context.Properties.IssuedUtc;
// Only validate if enough time has elapsed
var validate = issuedUtc == null;
if (issuedUtc != null)
{
DateTimeOffset lastValidateUtc;
if (IdentityValidationDates.TryGetValue(context.Identity.Name, out lastValidateUtc))
{
issuedUtc = lastValidateUtc;
}
var timeElapsed = currentUtc.Subtract(issuedUtc.Value);
validate = timeElapsed > validateInterval;
}
if (validate)
{
IdentityValidationDates[context.Identity.Name] = currentUtc;
var manager = context.OwinContext.GetUserManager<TManager>();
var userId = getUserIdCallback(context.Identity);
if (manager != null && userId != null)
{
var user = await manager.FindByIdAsync(userId);
var reject = true;
// Refresh the identity if the stamp matches, otherwise reject
if (user != null && manager.SupportsUserSecurityStamp)
{
var securityStamp = context.Identity.FindFirstValue(Constants.DefaultSecurityStampClaimType);
if (securityStamp == await manager.GetSecurityStampAsync(userId))
{
reject = false;
// Regenerate fresh claims if possible and resign in
if (regenerateIdentityCallback != null)
{
var identity = await regenerateIdentityCallback.Invoke(manager, user);
if (identity != null)
{
// Fix for regression where this value is not updated
// Setting it to null so that it is refreshed by the cookie middleware
context.Properties.IssuedUtc = null;
context.Properties.ExpiresUtc = null;
context.OwinContext.Authentication.SignIn(context.Properties, identity);
}
}
}
}
if (reject)
{
context.RejectIdentity();
context.OwinContext.Authentication.SignOut(context.Options.AuthenticationType);
}
}
}
};
}
}
标签:asp-net-identity,iis,asp-net,c,asp-net-mvc 来源: https://codeday.me/bug/20191120/2044748.html