5

背景

我正在开发从旧版 ASP.NET 表单应用程序到 MVC 4 应用程序的迭代迁移。

这种迁移是分阶段进行的,一次一个部分,因此有必要同时运行旧 MVC 应用程序和新 MVC 应用程序。对于某些部分,用户被引导到新应用程序,而对于尚未迁移的部分,用户被引导回(或保留在)旧应用程序。

在服务器上,应用程序的结构如下:

LEGACY (.NET 2.0 forms app)--
                            |--Api (new MVC 4 WebAPI)
                            |--V2 (new MVC 4)

foo因此,对 legacy 页面的调用是/foo.aspx,而在 V2 上是/V2/foo.

一切都在 C# 中,但请注意,旧版应用程序在 .NET 2.0 上运行,而 V2 应用程序在 .NET 4.5 上运行。我不确定这是否重要,但认为这很重要。

问题

我无法在应用程序之间成功共享用户/身份验证状态。显然,如果用户登录旧版应用程序,我需要在调用 V2 页面时在 V2 应用程序上获取他们的身份验证 cookie(或采取类似操作),以便用户不会再次收到登录提示。

我试过的

我在两个 web.config 文件中设置了相同的authentication和元素:machinekey

  <authentication mode="Forms">
      <forms cookieless="UseCookies" defaultUrl="~/someUrl" loginUrl="/" path="/" protection="All" timeout="240"  enableCrossAppRedirects ="true" domain="someDomain.com" requireSSL="false"  />
  </authentication>
  <machineKey validationKey="DE78CF63226. . .788658D142AB881" decryptionKey="0B97E8BA4C4EB4B4C524. . .54E4622E14168D2D5C84461FA2" validation="SHA1" decryption="AES" />

我在 V2 应用程序的 Global.asax 中尝试过这段代码:

protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
    string cookieName = FormsAuthentication.FormsCookieName;
    HttpCookie authCookie = Context.Request.Cookies[cookieName];

    if (authCookie == null)
    {
        return;
    }
    FormsAuthenticationTicket authTicket = null;
    try
    {
        authTicket = FormsAuthentication.Decrypt(authCookie.Value);
    }
    catch
    {
        return;
    }
    if (authTicket == null)
    {
        return;
    }
    string[] roles = authTicket.UserData.Split(new char[] { '|' });
    var id = new FormsIdentity(authTicket);
    var principal = new GenericPrincipal(id, roles);

    //Thread.CurrentPrincipal = principal;

    Context.User = principal;
}

但我不知道它是否有效,因为旧版应用程序与我的 V2 应用程序不在同一个解决方案中,因此当我调试 V2 应用程序时,我无法通过旧版应用程序登录并模拟在 legacy 和 V2 之间切换的实际用户体验。

我也刚刚尝试将其添加到我HomeController的列表中,希望相同的机器密钥对我有一些魔力:

 ViewBag.UserName = User.Identity.Name;

显然,然后我绑定ViewBag.UserName到视图中的一个 html 元素,但这似乎也不起作用。

4

3 回答 3

2

表单身份验证的签名和加密算法在 .NET 2.0 和 4.0 之间切换;所以在你的 4.0 配置中尝试

<appSettings>
    <add key="aspnet:UseLegacyFormsAuthenticationTicketCompatibility" value="true" />
    <add key="aspnet:UseLegacyEncryption" value="true" />
    <add key="aspnet:UseLegacyMachineKeyEncryption" value="true" />
</appSettings>

请注意,现在您有一个持久的身份验证方法来访问您的 webapi 端点,您很容易受到 CSRF 的攻击,您需要防范它。Mike Wasson在 asp.net 上有一个演练

于 2013-03-20T16:35:35.070 回答
2

在父应用上设置 machineKey compatibleMode="Framework20SP2"。

.net 4.5 无法从 4.0(或更低版本)读取身份验证令牌

http://technet.microsoft.com/en-us/subscriptions/index/system.web.configuration.machinekeycompatibilitymode

http://blogs.msdn.com/b/webdev/archive/2012/10/23/cryptographic-improvements-in-asp-net-4-5-pt-2.aspx

于 2013-03-21T01:10:27.787 回答
1

您为这两个应用程序使用的域/子域是什么?Cookie 不会在域甚至子域之间共享(除非 cookie 设置在通配符域上,即 *.mydomain.com)。

例如,如果 V1 应用程序位于 v1.somedomain.com 并且 cookie 设置在 v1.somedomain.com 上。然后在 v2.somedomain.com 上的 V2 将不到它。但是,如果您在 *.somedomain.com 上设置 cookie,那么两个应用程序都会看到 cookie。

但是,如果 V1 在 v1domain.com 上而 V2 在 v2domain.com 上,那么您就不走运了。无法共享 cookie。

于 2013-03-20T16:17:44.400 回答