【问题标题】:Clients need to delete cookies most of the times in MVC在 MVC 中客户端大部分时间都需要删除 cookie
【发布时间】:2011-10-20 12:48:13
【问题描述】:

我的 mvc 项目在我的本地机器上运行良好。但是,一旦发布到服务器上,用户在尝试访问该网站的第二次时间就无法访问登录。他们必须删除 cookie。为什么呢?我该如何纠正?

Global.asax.cs

 FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(Request.cookies[FormsAuthentication.FormsCookieName].Value);
 args.user = new MyProject.Web.UI.Classes.UserPrincipal(GetUserFromCache(ticket.Name))

源文件:c:\Myproject\Code\MvcUI\Global.asax.cs

    public void FormsAuthentication_OnAuthenticate(object sender, FormsAuthenticationEventArgs args)
    {
        if (FormsAuthentication.CookiesSupported)
        {
            if (null != Request.Cookies[FormsAuthentication.FormsCookieName])
            {
                FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value);
                args.User = new MyProject.Web.UI.Classes.UserPrincipal(GetUserFromCache(ticket.Name));
            }
        }
        else
            throw new HttpException("Cookieless Forms Authentication is not supported for this application.");
    }

    public void WindowsAuthentication_OnAuthenticate(object sender, WindowsAuthenticationEventArgs args)
    {
        string username = args.Identity.Name.Substring(args.Identity.Name.IndexOf("\\") + 1);
        Myproject.API.User user = GetUserFromCache(username);

        if (null == user)
            throw new HttpException("User could not be found.");

        args.User = new MyProject.Web.UI.Classes.UserPrincipal(user);
    }

帐户控制器

[HttpPost]
        public bool LogOn(string userName, string password, string returnUrl, bool rememberMe = false)
        {
            MyProject.API.User user = MyProject.API.User.Load(userName);
            string errorMessage = "Your user name and/or password is incorrect.";
            if (null != user && user.IsValidPassword(password))
            {
                user.LastLoginDate = DateTime.Now;
                user.Save();
                FormsAuthentication.SetAuthCookie(userName, rememberMe);
                return true;
            }
            else
                throw new Exception(errorMessage);
        }

web.config

    <?xml version="1.0"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=152368
  -->

<configuration>
    <configSections>
        <section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
        <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
            <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
            <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
        </sectionGroup>
    </configSections>

    <system.web.webPages.razor>
        <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <pages pageBaseType="System.Web.Mvc.WebViewPage">
            <namespaces>
                <add namespace="System.Web.Mvc" />
                <add namespace="System.Web.Mvc.Ajax" />
                <add namespace="System.Web.Mvc.Html" />
                <add namespace="System.Web.Routing" />
                <add namespace="MvcUI.HtmlHelpers" />
                <add namespace="MyProject.API" />
                <add namespace="MvcUI.Models" />
            </namespaces>
        </pages>
    </system.web.webPages.razor>


    <connectionStrings>
    <add name="ApplicationServices"
         connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true"
         providerName="System.Data.SqlClient" />
  </connectionStrings>

  <appSettings>
    <add key="ClientValidationEnabled" value="true"/> 
    <add key="UnobtrusiveJavaScriptEnabled" value="true"/> 
  </appSettings>

  <system.web>
    <compilation debug="true" targetFramework="4.0">
      <assemblies>
        <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
                <add assembly="Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" />
                <add assembly="Microsoft.ReportViewer.Common, Version=10.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" />
                <add assembly="Microsoft.Build.Framework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" />
                <add assembly="System.Management, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" />
      </assemblies>
            <buildProviders>
                <add extension=".rdlc" type="Microsoft.Reporting.RdlBuildProvider, Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            </buildProviders>
    </compilation>

    <authentication mode="Forms">
      <forms loginUrl="~/Account/LogOn" timeout="2880" />
    </authentication>

    <membership>
      <providers>
        <clear/>
        <add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="ApplicationServices"
             enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false"
             maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10"
             applicationName="/" />
      </providers>
    </membership>

    <profile>
      <providers>
        <clear/>
        <add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ApplicationServices" applicationName="/" />
      </providers>
    </profile>

    <roleManager enabled="false">
      <providers>
        <clear/>
        <add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="ApplicationServices" applicationName="/" />
        <add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" />
      </providers>
    </roleManager>

    <pages>
      <namespaces>
        <add namespace="System.Web.Helpers" />
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
        <add namespace="System.Web.WebPages"/>
      </namespaces>
    </pages>
        <httpHandlers>
            <add path="Reserved.ReportViewerWebControl.axd" verb="*" type="Microsoft.Reporting.WebForms.HttpHandler, Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
        validate="false" />
        </httpHandlers>
  </system.web>

    <nhibernate>
        <add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider"/>
        <add key="hibernate.dialect" value="NHibernate.Dialect.MsSql2000Dialect"/>
        <add key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver"/>
        <add key="hibernate.connection.connection_string" value="Server=.\SQLEXPRESS;Database=myDatabase;User=me;Pwd=password;"/>
        <add key="hibernate.show_sql" value="false"/>
    </nhibernate>

  <system.webServer>
    <validation validateIntegratedModeConfiguration="false"/>
    <modules runAllManagedModulesForAllRequests="true"/>
        <handlers>
            <add name="ReportViewerWebControlHandler" preCondition="integratedMode" verb="*" path="Reserved.ReportViewerWebControl.axd" type="Microsoft.Reporting.WebForms.HttpHandler, Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
        </handlers>
  </system.webServer>

  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

帐户模型

    public interface IFormsAuthenticationService
{
    void SignIn(string userName, bool createPersistentCookie);
    void SignOut();
}

public class FormsAuthenticationService : IFormsAuthenticationService
{
    public void SignIn(string userName, bool createPersistentCookie)
    {
        if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName");

        FormsAuthentication.SetAuthCookie(userName, createPersistentCookie);
    }

    public void SignOut()
    {
        FormsAuthentication.SignOut();
    }
}

错误消息指向 Gloabal.asax.cs 文件,如上所示。 错误信息:


我还包含了一个生成的机器密钥,但它没有解决问题,

【问题讨论】:

  • 您的网站是在 iis6/7 上运行的吗?
  • 在 iis6 和 7 上测试。两者相同
  • 你能发布更多代码来给我们提供流程上下文吗?
  • 如果没有上下文和一些真实的代码,这是不可能回答的。
  • @Darin,你需要什么信息,我可以发一下?

标签: asp.net-mvc-3 model-view-controller web-deployment


【解决方案1】:

根据您的反馈,您遇到该错误的原因可能是因为您正在为您的应用程序使用自动生成的machineKey(也可能在多台机器/应用程序池中,甚至在一个应用程序池中)回收太频繁)。

请务必查看this one

【讨论】:

  • @sra:这是一个完全不同的答案,我没有更新我的第一篇文章,因为它实际上可能会帮助遇到类似问题的其他人。
  • 我在使用Html.AntiForgeryToken() 时遇到了同样的问题(有一个不同的例外)。 cookie 的加密/解密过程是基于机器密钥的,所以在更换服务器时,cookie 无法解密。 web.config 文件中的一个简单的机器密钥就可以解决问题。
【解决方案2】:

你申请this patch了吗?

我看到您没有设置ticketCompatibilityMode,因为 .net 4 改变了加密的工作方式。

<forms 
    loginUrl="/Login.aspx" 
    timeout="2880" 
    ticketCompatibilityMode="Framework20"
    domain="domain.com"/>

检查您在两个系统上是否具有相同的机器密钥。确保你也应用了patch

由于该补丁修改了 ASP.NET 中某些功能的加密/签名行为,因此将其应用于网络场中的所有计算机非常重要。如果您有打补丁/未打补丁的混合匹配系统,您将有表单身份验证、webresource.axd 和 scriptresource.axd 请求成功/失败,具体取决于它们在场中命中的服务器(因为使用的加密将是不同)。

【讨论】:

    【解决方案3】:

    如果请求经过身份验证,我假设您的用户在到达登录页面时会被重定向到某个地方,因此他们在第一次成功登录后无法访问登录页面。

    如果是这种情况,您可能希望在第一次加载页面时强制您的用户在到达登录页面时退出。例如(Razor 语法,C#):

    @if (!IsPost && Request.IsAuthenticated)
    {
        FormsAuthentication.SignOut();
    }
    

    【讨论】:

    • 我根本无法访问登录表单
    【解决方案4】:

    在 LogOn 操作方法的 GET(不是 post)上。检查用户是否已通过身份验证,如果是,请注销。

    if (System.Web.HttpContext.Current.User.Identity.IsAuthenticated)
    {
         FormsAuthentication.SignOut();
    }
    

    【讨论】:

      【解决方案5】:

      感谢大家尝试回答问题。确实,他们都很有帮助。我通过在 wenconfig 中添加一个机器密钥自己解决了这个问题,并且必须有一个表单名称。没有表单名,连机器键都没用

      【讨论】:

        猜你喜欢
        • 2012-08-30
        • 1970-01-01
        • 2019-09-24
        • 1970-01-01
        • 2018-03-06
        • 1970-01-01
        • 1970-01-01
        • 2018-09-01
        • 1970-01-01
        相关资源
        最近更新 更多