在 asp.net webforms 站点和 .net core 3.1 站点中使用相同的 cookie

如何解决在 asp.net webforms 站点和 .net core 3.1 站点中使用相同的 cookie

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

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

根据我所做的研究,使用 webforms 身份验证和 .net core 似乎不可能做到这一点。但是,是否可以使用 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>

解决方法

我能够通过这个 guide、这个 video 解决这个问题,并且通过其他研究对 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 演练 here 中进行了说明,但总而言之,您希望将两个站点的身份验证类型、cookie 名称、应用程序名称和密钥设置为相同。此外,请确保此 cookie 的登录和注销路径指向 .net core 登录和注销路径,以便可以将所有身份验证 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 core 站点上存储我的 cookie 名称、cookie 身份验证类型、cookie 密钥位置和应用程序名称。

在构建之前,您需要确保已安装所有 nuget 包,并且您已在 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。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res