【问题标题】:Use the same cookie across asp.net webforms site and .net core 3.1 site在 asp.net webforms 站点和 .net core 3.1 站点中使用相同的 cookie
【发布时间】:2021-06-28 19:25:10
【问题描述】:

我在同一个域上运行一个 asp.net Framework 4.8 webforms 项目和一个 asp.net core 3.1 项目,每个项目都有单独的子域。

我希望能够让用户在新站点上使用 .net 核心身份登录,这将为他们分配一个 cookie,并让该 cookie 使用 Owin 中间件在旧的 webforms 应用程序上对他们进行身份验证。

从我所做的研究看来,使用 webforms 身份验证和 .net 核心似乎无法做到这一点。但是,是否可以使用 microsoft.aspnet.identity 和 Owin 中间件?我能否以某种方式使用 Owin 中间件解密 webforms 站点上的 .net 核心 cookie,并使用它为 webforms 站点设置 aspnet.identity cookie 的声明,或者只是将这些声明注入旧应用程序,这样我就可以拥有我的 HttpContext 用户身份想过这个应用程序吗?

据说John Geddes 找到了解决方案,但没有时间分享他所做的事情(请参阅他对此answer 的评论)。他说他在 .net framework webforms 应用上使用了 Owin,但没有提供更多细节。

这是我的 .net core 启动类

 public class Startup
    {
        public IConfiguration Configuration { get; }
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }


        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
          
            services.AddIdentity<User, IdentityRole>(cfg =>
            {
                cfg.User.RequireUniqueEmail = true;
            })
               .AddEntityFrameworkStores<SJRContext>()
               .AddSignInManager<SJRSignInManager<User>>()
               .AddDefaultTokenProviders()
               .AddTokenProvider<CustomTwoFactorTokenProvider<User>>("TwoFactorAuthToken");

            //cookie is added here
            services.AddAuthentication()
                .AddCookie(cfg =>
                {
                    cfg.ExpireTimeSpan = TimeSpan.FromMinutes(20);
                    cfg.LoginPath = @"/Account/Login";
                    cfg.LogoutPath = @"/Account/Logout";
                    cfg.SlidingExpiration = true;
                    cfg.Cookie.Expiration = TimeSpan.FromMinutes(30);
                    cfg.Cookie.Domain = Configuration.GetSection("AppDomain").Value;
                }); 

            //More service set up here...

            services.AddSession();
        }

        public void OnShutdown()
        {
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {

            //More middleware here...

            app.Use(async (ctx, next) =>
            {
                //Get and set cookie exp date according to ip address and client device here

                //Go to next middleware
                await next();

            });


            //More middleware here....

            app.UseAuthorization();

           
        }
    }

这是在asp.net framework 4.8 webforms上设置cookie的Web.config

 <system.web>
    <authentication mode="Forms">
      <!-- Set login to login page for development -->
      <forms loginUrl="~/Account/Login.aspx" name=".AspNetCore.Identity.Application" enableCrossAppRedirects="true" cookieless="UseCookies" requireSSL="false" timeout="60" slidingExpiration="true" />
    </authentication>
    <authorization>
      <deny users="?" />
      <allow users="*" />
    </authorization>
  </system.web>

这是我的 web.release.config 文件,用于在发布模式下覆盖上述文件

 <system.web>
    <authentication mode="Forms">
      <!-- Set login to .net core login page for production (Release)-->

      <forms loginUrl="https://MyDotNetCoreSubDomain.SharedDomain.com/Account/Login" enableCrossAppRedirects="true" name=".AspNetCore.Identity.Application" cookieless="UseCookies" requireSSL="false" timeout="4320" domain=".SharedDomain.com" slidingExpiration="true" xdt:Transform="Replace"/>
    </authentication>
  </system.web>

【问题讨论】:

  • 嗨@BoMerican,正如答案所说,在网络表单和asp.net核心之间共享cookie是不可能的。
  • Rena,是的,但是如果您查看 @JohnGeddes 对 answer 的评论,他最终会弄清楚如何使用 Owin 中间件。这就是我现在想要弄清楚的。我想慢慢升级我的旧网络表单应用,而不是强迫用户分别登录这两个应用。
  • @Rena 我更新了我的问题,以便更清楚地了解我想要去的方向。

标签: asp.net .net asp.net-core cookies webforms


【解决方案1】:

我能够通过guidevideo 解决这个问题,并通过其他研究了解了 cookie 的工作原理。我将概述完成这项工作的过程,并将我的代码显示为示例。

总结:简单地说,cookie 身份验证会加密一个 cookie(或使用 cookie 块的多个 cookie)上的主体(用户身份),并将该 cookie 提供给客户端(用户)。每次客户端向服务器发出请求时,它们都会包含 cookie,服务器需要解密该 cookie。为了跨多个 Web 应用程序执行此操作,我们将加密密钥存储在两个应用程序都可以访问它并使用身份处理解密的地方。请注意,您需要保护此密钥,因为您的应用的安全性取决于它。

配置 .net core 3.1 站点的启动。这也适用于 .net core 2.x。

  1. 设置身份
 services.AddIdentity<User, IdentityRole>(cfg =>
 {
   cfg.User.RequireUniqueEmail = true;
 })
   .AddEntityFrameworkStores<SJRContext>()
   .AddSignInManager<SJRSignInManager<User>>()
   .AddDefaultTokenProviders();
  1. 设置数据保护(使用该加密密钥)
services.AddDataProtection()
   .PersistKeysToFileSystem(new DirectoryInfo(Configuration.GetSection("SharedCookie:CookieKeys").Value))
.SetApplicationName(Configuration.GetSection("SharedCookie:CookieApplicationName").Value);
  1. 设置 cookie(在我的例子中,我设置了 cookie 域并为每个网站使用不同的子域)。
services.ConfigureApplicationCookie(opt =>
{
    opt.Cookie.Name = Configuration.GetSection("SharedCookie:CookieName").Value;
    opt.Cookie.Domain = Configuration.GetSection("AppDomain").Value;
    opt.Cookie.Path = "/";
});

接下来我需要配置我的旧 .net framework 4.8 webforms 站点以停止使用 webforms 身份验证并改用 owin 中间件。这样我就可以使用身份来解密共享的 cookie。

为此,我需要创建一个 Startup 类和 startup.auth 类 这个video 引导我完成了这个。

  1. 这是我的入门课程
Imports Microsoft.Owin
Imports Owin

<Assembly: OwinStartup(GetType(Startup))>
Partial Public Class Startup
    Public Sub Configuration(ByVal app As IAppBuilder)
        ConfigureAuth(app)
    End Sub
End Class

请注意,这部分代码告诉 owin 将其用作启动类:

<Assembly: OwinStartup(GetType(Startup))>
  1. 在我的 startup.auth 类中,我放置了我所有的身份验证逻辑。

这部分变得复杂,很容易复制和粘贴,并且不明白发生了什么。这部分过程在 Microsoft walk through here 中进行了说明,但总而言之,您希望将两个站点的身份验证类型、cookie 名称、应用程序名称和密钥设置为相同。此外,请确保此 cookie 的登录和注销路径指向 .net 核心登录和注销路径,以便可以作为所有身份验证 cookie 分发的地方。

Imports System.IO
Imports Microsoft.AspNet.Identity.Owin
Imports Microsoft.AspNetCore.DataProtection
Imports Microsoft.Owin
Imports Microsoft.Owin.Security.Cookies
Imports Microsoft.Owin.Security.Interop
Imports Owin


Partial Public Class Startup
    Public Sub ConfigureAuth(ByVal app As IAppBuilder)

        app.UseCookieAuthentication(New CookieAuthenticationOptions With
        {
            .AuthenticationType = ConfigurationManager.AppSettings.Get("CookieAuthenticationType"),
            .CookieName = ConfigurationManager.AppSettings.Get("CookieName"),
            .LoginPath = New PathString(ConfigurationManager.AppSettings.Get("workordersWebAddress") + "Account/Login"),
            .LogoutPath = New PathString(ConfigurationManager.AppSettings.Get("workordersWebAddress") + "Account/Logout"),
            .Provider = New CookieAuthenticationProvider With
            {
                .OnValidateIdentity = SecurityStampValidator.OnValidateIdentity(Of ApplicationUserManager, ApplicationUser)(
                    validateInterval:=TimeSpan.FromMinutes(30),
                    regenerateIdentity:=Function(manager, user) user.GenerateUserIdentityAsync(manager))
            },
            .TicketDataFormat = New AspNetTicketDataFormat(
                New DataProtectorShim(
                    DataProtectionProvider.Create(New DirectoryInfo(ConfigurationManager.AppSettings.Get("CookieKeys")),
                        Function(builder) builder.SetApplicationName(ConfigurationManager.AppSettings.Get("CookieApplicationName"))
                    ).CreateProtector(
                        "Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware",
                        ConfigurationManager.AppSettings.Get("CookieAuthenticationType"),
                        "v2"
                    )
                )
            ),
            .CookieManager = New ChunkingCookieManager()
        })
    End Sub
End Class

请注意我在 webforms 网站上使用我的 web.config 文件和 appsettings.json 文件 在我的 .net 核心站点上存储我的 cookie 名称、cookie 身份验证类型、cookie 密钥位置和应用程序名称。

在构建之前,您需要确保所有 nuget 包都已安装,并且您已在 webforms 应用程序上正确设置了您的身份。我不打算在整个 webforms 应用程序中使用身份和角色,因此我将向您展示如何使其仅适用于 cookie。

创建应用程序用户。注意我没有设置任何属性。我只是从 IdentityUser 对象继承属性。

Imports System.Security.Claims
Imports System.Threading.Tasks
Imports Microsoft.AspNet.Identity
Imports Microsoft.AspNet.Identity.EntityFramework

Public Class ApplicationUser
    Inherits IdentityUser

    Public Async Function GenerateUserIdentityAsync(ByVal manager As UserManager(Of ApplicationUser)) As Task(Of ClaimsIdentity)
        ' The authenticationType must match the one defined in 
        ' CookieAuthenticationOptions.AuthenticationType
        Dim userIdentity = Await manager.CreateIdentityAsync(Me, ConfigurationManager.AppSettings.Get("CookieName"))

        ' Add custom user claims here
        Return userIdentity
    End Function
End Class

接下来创建用户管理器。

Imports Microsoft.AspNet.Identity
Imports Microsoft.AspNet.Identity.EntityFramework
Imports Microsoft.AspNet.Identity.Owin
Imports Microsoft.Owin

Public Class ApplicationUserManager
    Inherits UserManager(Of ApplicationUser)
    Public Sub New(ByVal store As IUserStore(Of ApplicationUser))
        MyBase.New(store)

    End Sub

    Public Shared Function Create(ByVal options As IdentityFactoryOptions(Of ApplicationUserManager), ByVal context As IOwinContext) As ApplicationUserManager
        Dim store = New UserStore(Of ApplicationUser)(context.Get(Of WorkordersDatabase.SJContext)())
        Dim manager = New ApplicationUserManager(store)
        Return manager
    End Function
End Class

在您的身份用户和用户管理器指向您的 .net 核心应用指向的相同 dbcontext 之后,您现在应该能够解密两个站点上的这些 cookie。

【讨论】:

    猜你喜欢
    • 2020-09-02
    • 2021-03-15
    • 2020-12-07
    • 1970-01-01
    • 2022-01-18
    • 2020-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多