You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET MVC项目能否共存表单认证与Azure AD SAML认证及实现方法

ASP.NET MVC(非Core)整合表单认证与Azure AD SAML认证方案

可行性与共存说明

完全可行,两种认证方式可以在同一项目中共存。Owin中间件支持同时配置多种认证方案,通过不同的AuthenticationType标识区分,最终无论用户通过哪种方式登录,都会生成统一的应用认证Cookie,让系统后续的授权逻辑无需做额外修改。

具体实现步骤

1. 安装依赖NuGet包

需要添加SAML认证相关的Owin包,在NuGet包管理器中安装:
Microsoft.Owin.Security.Saml2

2. 配置Azure AD应用信息

在Azure AD中注册SAML企业应用,获取以下关键信息并添加到Web.config的<appSettings>节点:

  • AzureAD:EntityId:Azure AD的SAML实体ID
  • AzureAD:ACSUrl:项目接收SAML响应的回调地址(示例:https://yourdomain.com/signin-saml)
  • AzureAD:MetadataAddress:Azure AD元数据地址
  • AzureAD:Certificate:Azure AD提供的签名证书(用于验证SAML响应)

示例Web.config配置:

<appSettings>
  <!-- 原有配置 -->
  <add key="AzureAD:EntityId" value="https://sts.windows.net/your-tenant-id/" />
  <add key="AzureAD:ACSUrl" value="https://yourdomain.com/signin-saml" />
  <add key="AzureAD:MetadataAddress" value="https://login.microsoftonline.com/your-tenant-id/federationmetadata/2007-06/federationmetadata.xml" />
</appSettings>

3. 修改Startup类,添加SAML认证中间件

在现有Cookie认证配置基础上,添加SAML认证配置,同时调整Cookie认证的LoginPath指向登录选择页面。修改后的Startup代码如下:

Imports Microsoft.AspNet.Identity
Imports Microsoft.AspNet.Identity.EntityFramework
Imports Microsoft.AspNet.Identity.Owin
Imports Microsoft.Owin
Imports System.Web.Configuration
Imports Owin
Imports Microsoft.Owin.Security.Cookies
Imports Microsoft.Owin.Security.Saml2

Public Class Startup 
    Public Sub Configuration(app As IAppBuilder)
        Dim timeoutKey As Integer = Integer.Parse(WebConfigurationManager.AppSettings("timeOut"))

        app.CreatePerOwinContext(Function() New Entities())
        app.CreatePerOwinContext(Of UserManager)(Function() UserManager.Create(Nothing, HttpContext.Current.GetOwinContext()))
        app.CreatePerOwinContext(Of RoleManager(Of Role))(Function(options, context) New RoleManager(Of Role)(New RoleStore(Of Role)(context.Get(Of Entities)())))

        ' 配置Cookie认证(统一应用会话)
        app.UseCookieAuthentication(New CookieAuthenticationOptions() With {
            .AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            .Provider = New CookieAuthenticationProvider() With {
                .OnResponseSignIn = Sub(context)
                                      context.Properties.AllowRefresh = True
                                      context.Properties.ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(timeoutKey)
                                    End Sub
            },
            .SlidingExpiration = True,
            .CookieName = WebConfigurationManager.AppSettings("cookie"),
            .CookieHttpOnly = True,
            .CookieSecure = CookieSecureOption.Always,
            .CookieSameSite = SameSiteMode.Lax,
            .ExpireTimeSpan = TimeSpan.FromMinutes(timeoutKey),
            .LoginPath = New PathString("/Account/LoginSelection"), ' 指向登录选择页面
            .LogoutPath = New PathString("/Account/Logout"),
            .ReturnUrlParameter = "ReturnTo"
        })

        ' 添加SAML认证中间件
        app.UseSaml2Authentication(New Saml2AuthenticationOptions() With {
            .AuthenticationType = "AzureAD-SAML",
            .Caption = "登录Azure AD",
            .MetadataAddress = WebConfigurationManager.AppSettings("AzureAD:MetadataAddress"),
            .EntityId = WebConfigurationManager.AppSettings("AzureAD:EntityId"),
            .CallbackPath = New PathString("/signin-saml"),
            .SignInAsAuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, ' 认证成功后转换为应用Cookie
            .Provider = New Saml2AuthenticationProvider() With {
                .OnAuthenticated = Sub(context)
                                      ' 处理Azure AD返回的用户信息,映射到本地用户
                                      Dim email = context.AuthenticationTicket.Identity.FindFirst(System.Security.Claims.ClaimTypes.Email)?.Value
                                      ' 可在此创建本地用户或关联已有用户,添加自定义Claim等
                                    End Sub
            }
        })
    End Sub
End Class

4. 创建登录选择页面

新建Account/LoginSelection.cshtml视图,提供两个登录选项:

<div>
    <h2>选择登录方式</h2>
    @using (Html.BeginForm("Login", "Account", FormMethod.Post))
    {
        <button type="submit">用户名/密码登录</button>
    }
    <a href="/Account/LoginWithAzureAD" class="btn">Azure AD登录</a>
</div>

5. 添加登录动作方法

在AccountController中添加触发SAML登录的方法:

<AllowAnonymous>
Public Function LoginWithAzureAD() As ActionResult
    ' 触发SAML认证流程
    Return New ChallengeResult("AzureAD-SAML", Url.Action("Index", "Home"))
End Function

' 原有表单登录方法保持不变
<HttpPost>
<AllowAnonymous>
Public Async Function Login(model As LoginViewModel) As Task(Of ActionResult)
    ' 原有表单认证逻辑
End Function

6. 处理用户映射与授权

在SAML的OnAuthenticated事件中,将Azure AD返回的用户信息(如邮箱、姓名)与本地系统用户关联:

  • 若本地已有该用户,直接关联;
  • 若没有,可根据业务需求自动创建本地用户;
  • 添加必要的Claim到认证票据,确保后续授权逻辑能识别用户角色或权限。

关键注意事项

  • 确保Azure AD应用配置的ACS URL与项目中CallbackPath完全一致,包括HTTPS协议;
  • 生产环境务必启用CookieSecure = CookieSecureOption.Always,确保Cookie仅通过HTTPS传输;
  • 测试时用Azure AD测试用户验证SAML流程,同时保留原有表单认证测试用例。

内容的提问来源于stack exchange,提问作者Oumi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 05:54:59