Asp.net表单身份验证-主体更改?

Asp.net表单身份验证-主体更改?,asp.net,c#-4.0,webforms,Asp.net,C# 4.0,Webforms,我在表单身份验证方面遇到了一个奇怪的问题。我有自己的自定义主体和标识类,登录后我将HttpContext.Current.User设置为该主体,并将其存储在缓存(HttpContext.Current.cache)中。似乎过了一段时间,奇怪的行为开始了。这是我的AuthenticateRequest处理程序: protected void Application_AuthenticateRequest( object sender, EventArgs e ) { string user

我在表单身份验证方面遇到了一个奇怪的问题。我有自己的自定义主体和标识类,登录后我将HttpContext.Current.User设置为该主体,并将其存储在缓存(HttpContext.Current.cache)中。似乎过了一段时间,奇怪的行为开始了。这是我的AuthenticateRequest处理程序:

protected void Application_AuthenticateRequest( object sender, EventArgs e ) {
    string userName;

    var formAuthCookie = HttpContext.Current.Request.Cookies[ FormsAuthentication.FormsCookieName ];
    var isAuthenticated = HttpContext.Current.Request.IsAuthenticated;

    if ( isAuthenticated || formAuthCookie != null ) {
        if ( !isAuthenticated ) {
            var ticket = FormsAuthentication.Decrypt( formAuthCookie.Value );
            userName = ticket.Name;
        }
        else {
            userName = HttpContext.Current.User.Identity.Name;
        }

        var prin = (IPrincipal)HttpContext.Current.Cache[ userName ];

        if ( prin != null ) {
            HttpContext.Current.User = prin;
        }
    }
}
这总是好的;自定义主体从缓存中提取并正确设置为当前上下文的用户

问题是,当我进入页面加载时,page.User属性有一个GenericPrincipal(没有角色)和一个FormSidenty。我不知道这发生在哪里。当然,由于用户的角色不正确,页面无法正常工作,尽管FormsAuth允许用户进入角色受限的页面

你知道为什么我在AuthenticateRequest处理程序中设置的princpal会被替换吗?

试试这个:

var formAuthCookie = Context.Request.Cookies[ FormsAuthentication.FormsCookieName ]; 
var isAuthenticated = Context.Request.IsAuthenticated; 

if ( isAuthenticated || formAuthCookie != null ) { 
    if ( !isAuthenticated ) { 
        var ticket = FormsAuthentication.Decrypt( formAuthCookie.Value ); 
        userName = ticket.Name; 
    } 
    else { 
        userName = Context.User.Identity.Name; 
    } 

    var prin = (IPrincipal)Context.Cache[ userName ]; 

    if ( prin != null ) { 
        Context.User = prin; 
    } 
} 

您确实意识到FormsAuthentication是基于cookie的,而cache是基于AppDomain的,这意味着每次应用程序域恢复时,所有内容都会丢失……应用程序池不会被回收。事实上,你提醒了我,回收应用程序池似乎可以解决一点问题。cookie设置为与会话同时过期。问题不是缓存丢失,因为我可以跟踪上面的代码,看到正确的主体被拉出,几秒钟后在页面加载中,我有一个不同的主体。您不应该将会话设置为与表单验证cookie同时过期@MystereMan提供了很好的信息,但此问题在登录后立即发生。它从.Net 2.0开始一直正常工作,直到最近。我总是使用Context.User而不是HttpContext.Current.User,不确定是否有区别。你能强调一下这和我的区别吗?@Andy-这是一个小代码块,变化很明显。您只需将HttpContext.Current.*更改为Context.*@bang-这是有区别的。相信我,这件事我自己也做了。区别在于Context.*是HttpContext的包装器,如果您将其设置在错误的位置,该包装器将被重置(清除更改)。@MystereMan抱歉。我以为是你提到的Page.Context而不是global.asax。听起来很奇怪,但你可能就在这里。从不使用global.asax。你能解释一下为什么它们是不同的吗?使用Global.asax,你只需编写一次代码,它适用于所有东西。它不需要复制代码,也不需要使用公共基类。至于为什么在这里会有不同,MVC将上下文包装在一个shim类中,以使测试更容易。如果在创建此垫片后更改HttpContext,则旧值仍将存在于包装器类中,即使它们存在于HttpContext中。你不想把两者混为一谈。要么只使用包装器,要么只使用HttpContext。