向经典 ASP.NET Web 窗体应用和 Web API 应用添加共享身份验证

Posted

技术标签:

【中文标题】向经典 ASP.NET Web 窗体应用和 Web API 应用添加共享身份验证【英文标题】:Add shared authentication to a Classic ASP.NET Web Forms app and a Web API app 【发布时间】:2021-02-27 05:27:06 【问题描述】:

我正在用 Open Id Connect 替换共享 cookie 身份验证设计。

上下文:这两个网络应用程序当前使用FormsAuthentication,共享AuthCookie cookie 和machineKeys

系统:

经典的 Web 表单应用程序,FormsAuthentication,cookie=AuthCookie,主机/login.aspx 一个集成的 Web API 应用程序,FormsAuthentication,cookie=AuthCookie

问题 1:Microsoft 的 Open Id Connect 库需要 OWIN。我无法将经典 Web 窗体应用程序转换为 OWIN 应用程序,因为 OWIN 需要集成管道,这会破坏依赖于经典管道的 Spring.NET 库。

操作 1A:将 Web API 转换为 OWIN 并添加对 Open Id Connect 的支持。

操作 1B:将身份验证从经典站点转移到 Web API。

问题 2:身份验证后,我必须能够同时使用这两个系统。

操作 2:在 Open Id Connect 重定向时,Web API 将使用存储在 Open Id Connect cookie 中的 JWT 不记名令牌。 Web API 将创建一个额外的 cookie (AuthCookie),经典应用将使用该 cookie。

问题 3:如何使这两个 cookie 保持同步?用户必须同时登录或退出这两个系统。如果一个 cookie 被意外删除而另一个没有被删除,会发生什么?

问题 4:Web API 未从 Microsoft Open Id Connect 接收 cookie,但对我的 Web API 的后续请求未收到 cookie,并且未设置 HttpContext.Current.User

经典 Web 表单代码:

<authentication mode="Forms">
        <forms loginUrl="webapi/login" name="LycheeAuthCookie" slidingExpiration="true" path="/" />
</authentication>

Web API 代码:

Startup.cs:
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions  AuthenticationMode = AuthenticationMode.Passive ); //Web API should return 401 not redirect to /login. The SPA will handle that
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions

                ClientId = Config.ApplicationId,
                Authority = authority,
                RedirectUri = $"webapi/openIdRedirect",
                PostLogoutRedirectUri = $"webapi/openIdLogout",
                ResponseType = OpenIdConnectResponseType.IdToken,
                Scope = OpenIdConnectScope.OpenIdProfile,
                AuthenticationMode = AuthenticationMode.Passive, //Web API should return 401 not redirect to /login. The SPA will handle that
);
...
private Task OnSecurityTokenValidated(SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context) //Called on Open Id Connect authentication success
        
            var newTicket = new FormsAuthenticationTicket(1,
                userId,
                DateTime.Now.AddMinutes(int.Parse(claims.FindFirst("iat").Value)),
                false,
                DateTime.Now.AddMinutes(int.Parse(claims.FindFirst("exp").Value)),
                false,
                "roles and permissions",
                FormsAuthentication.FormsCookiePath);
            var cookie = new HttpCookie("AuthCookie");
            cookie.Value = FormsAuthentication.Encrypt(newTicket);
            cookie.Expires = newTicket.Expiration;
            HttpContext.Current.Response.Cookies.Add(cookie);

Redirect(redirectUrl);

【问题讨论】:

【参考方案1】:

如果您将您的网站托管在同一个域上,即“https://localhost”,并且您共享相同的.AspNet.Cookies,那么它将起作用!

为这两个网站添加OWIN中间件,将您的项目设置为IIS集成管道模式,并添加以下Startup.cs文件:

“/”处的网站 1 - 活动:

[assembly: OwinStartup(typeof(...MyStartup))]
namespace MyNamespace

    public class Startup
    
        public void Configuration(IAppBuilder app)
        
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
            app.UseCookieAuthentication();
            app.UseOpenIdConnectAuthentication();
        
    

位于“/api”的网站 2 - 被动:

[assembly: OwinStartup(typeof(...MyStartup))]
namespace MyNamespace

    public class Startup
    
        public void Configuration(IAppBuilder app)
        
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
            app.UseCookieAuthentication(new Microsoft.Owin.Security.Cookies.CookieAuthenticationOptions 
                AuthenticationType = CookieAuthenticationDefaults.AuthenticationType
            );
        
    

【讨论】:

以上是关于向经典 ASP.NET Web 窗体应用和 Web API 应用添加共享身份验证的主要内容,如果未能解决你的问题,请参考以下文章

在 ASP.NET Web 窗体中的特定 URL 上启用 CORS

VS2012创建ASP.NET WEB窗体应用程序失败?

如何在 ASP.NET Web 窗体环境中使用 DLL?

一个简单的ASP.NET Web Forms应用程序

ASP.NET Web 窗体和 ASP.NET 网页

ASP.NET Web 窗体中的输出编码安全问题