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

如何为已完成开发的C# MVC应用集成On-Premise ADFS 2.0认证?

事后接入ADFS 2.0的C# MVC应用集成方案

刚好之前帮几个客户处理过这种开发完成后才接入ADFS的场景,给你一套落地性很强的方案,一步步来就能搞定:

1. 先安装必要的NuGet包

因为是.NET Framework的MVC项目,推荐用OWIN的WsFederation中间件(比传统的WIF更灵活易维护)。打开NuGet包管理器控制台,运行以下命令:

Install-Package Microsoft.Owin.Security.WsFederation
Install-Package Microsoft.Owin.Host.SystemWeb
Install-Package Owin

2. 配置OWIN Startup类

如果你的项目还没有OWIN Startup类,直接在项目根目录新建一个Startup.cs,然后添加认证配置:

using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.WsFederation;
using Owin;
using System.Threading.Tasks;
using System.Security.Claims;

[assembly: OwinStartup(typeof(YourMvcAppNamespace.Startup))]
namespace YourMvcAppNamespace
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            // 启用Cookie认证,用来存储ADFS返回的用户身份
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
                LoginPath = new PathString("/Account/Login"), // 触发ADFS登录的入口
                ExpireTimeSpan = System.TimeSpan.FromHours(8)
            });

            // 配置WsFederation对接ADFS
            app.UseWsFederationAuthentication(new WsFederationAuthenticationOptions
            {
                // ADFS元数据地址,自动获取ADFS的配置信息
                MetadataAddress = "https://your-adfs-server/FederationMetadata/2007-06/FederationMetadata.xml",
                // 必须和ADFS里为你的应用配置的Realm完全一致
                Wtrealm = "urn:your-mvc-app-realm",
                // 回调地址,也要在ADFS的应用注册里配置好
                Wreply = "https://your-mvc-app-domain/",
                AuthenticationType = "WsFederation",
                // 自定义声明处理的通知事件
                Notifications = new WsFederationAuthenticationNotifications
                {
                    SecurityTokenValidated = context =>
                    {
                        // 这里可以根据业务需求处理ADFS返回的声明
                        var identity = context.AuthenticationTicket.Identity;
                        // 示例:把ADFS的NameIdentifier声明映射为应用内的用户名
                        var nameClaim = identity.FindFirst(ClaimTypes.NameIdentifier);
                        if (nameClaim != null)
                        {
                            identity.AddClaim(new Claim(ClaimTypes.Name, nameClaim.Value));
                        }
                        return Task.CompletedTask;
                    }
                }
            });
        }
    }
}

3. 修改Web.config的认证授权配置

找到<system.web>节点,更新认证模式和默认授权规则:

<system.web>
    <!-- 禁用Forms认证,交给OWIN处理 -->
    <authentication mode="None" />
    <authorization>
        <!-- 默认拒绝所有匿名访问,需要认证才能进入应用 -->
        <deny users="?" />
    </authorization>
</system.web>

如果有不需要认证的页面(比如首页、静态资源),可以添加<location>节点单独配置:

<location path="Home/Index">
    <system.web>
        <authorization>
            <allow users="*" />
        </authorization>
    </system.web>
</location>

4. 实现ADFS登录触发逻辑

在你的AccountController里添加Login方法,用来触发ADFS的认证流程:

using System.Web;
using System.Web.Mvc;
using Microsoft.Owin.Security;

public class AccountController : Controller
{
    public ActionResult Login(string returnUrl)
    {
        if (!Request.IsAuthenticated)
        {
            // 触发ADFS登录请求,登录成功后跳转到指定页面
            var properties = new AuthenticationProperties { RedirectUri = returnUrl ?? Url.Action("Index", "Home") };
            HttpContext.GetOwinContext().Authentication.Challenge(properties, "WsFederation");
            return new HttpUnauthorizedResult();
        }
        return RedirectToAction("Index", "Home");
    }

    // 实现登出逻辑,同时通知ADFS注销
    public ActionResult Logout()
    {
        HttpContext.GetOwinContext().Authentication.SignOut(
            CookieAuthenticationDefaults.AuthenticationType, 
            "WsFederation");
        return RedirectToAction("Index", "Home");
    }
}

5. 访问和使用ADFS声明

在控制器里,你可以通过User.Identity获取ADFS返回的所有声明,比如在Profile页面展示用户信息:

public ActionResult Profile()
{
    var claimsIdentity = User.Identity as ClaimsIdentity;
    if (claimsIdentity != null)
    {
        var userClaims = claimsIdentity.Claims.ToList();
        // 可以把声明传给视图展示,或者用来做业务逻辑判断
        return View(userClaims);
    }
    return View();
}

如果需要全局处理声明(比如添加角色、转换声明格式),可以自定义ClaimsAuthenticationManager:

public class CustomClaimsManager : ClaimsAuthenticationManager
{
    public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
    {
        if (!incomingPrincipal.Identity.IsAuthenticated)
        {
            return base.Authenticate(resourceName, incomingPrincipal);
        }

        var identity = (ClaimsIdentity)incomingPrincipal.Identity;
        // 示例:根据ADFS的Email声明添加角色
        var emailClaim = identity.FindFirst(ClaimTypes.Email);
        if (emailClaim?.Value == "admin@yourcompany.com")
        {
            identity.AddClaim(new Claim(ClaimTypes.Role, "Administrator"));
        }

        return new ClaimsPrincipal(identity);
    }
}

然后在Web.config里注册这个管理器:

<system.identityModel>
    <identityConfiguration>
        <claimsAuthenticationManager type="YourMvcAppNamespace.CustomClaimsManager, YourMvcAppNamespace" />
    </identityConfiguration>
</system.identityModel>

6. 必踩坑的注意事项

  • ADFS配置必须完全一致:Wtrealm和Wreply的取值要和ADFS服务器上为你的应用配置的完全相同,包括URL的大小写、是否带斜杠,而且必须是HTTPS(ADFS 2.0强制要求)。
  • 元数据地址可访问:确保应用服务器能正常访问ADFS的元数据URL,否则会出现配置加载失败的问题。
  • 启用HTTPS:本地开发可以用自签名证书,生产环境必须用正规SSL证书,否则ADFS会拒绝回调请求。
  • 调试声明:登录后可以打印所有声明,确认ADFS返回的内容是否符合预期,方便后续业务逻辑对接。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:19:46