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

如何结合ASP.NET Identity与Sustainsys库实现Azure AD SAML2单点登录?

使用Sustainsys.SAML2结合ASP.NET Identity实现Azure AD SSO

以下是完整的集成步骤与代码示例:

1. 安装必要的NuGet包

在项目中安装依赖包:

Install-Package Sustainsys.Saml2.AspNetCore2
Install-Package Microsoft.AspNetCore.Identity.EntityFrameworkCore

2. 准备Azure AD SAML配置

在Azure门户完成基础配置:

  • 创建企业应用程序,启用SAML单点登录
  • 记录Azure AD标识符(即SAML实体ID)和SAML元数据URL
  • 设置回复URL(ACS URL)为你的应用地址 + /saml2/acs(例如:https://your-app.com/saml2/acs)

3. 配置服务与中间件(Program.cs)

注册Identity与SAML服务

var builder = WebApplication.CreateBuilder(args);

// 注册Identity服务
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();

// 配置Sustainsys.SAML2
builder.Services.AddSaml2(options =>
{
    // 设置应用自身的SAML实体ID
    options.SPOptions.EntityId = new EntityId("https://your-app.com");
    // 添加Azure AD作为身份提供商
    options.IdentityProviders.Add(new IdentityProvider(
        new EntityId("https://sts.windows.net/your-tenant-id/"), // Azure AD标识符
        options.SPOptions)
    {
        MetadataLocation = "https://login.microsoftonline.com/your-tenant-id/federationmetadata/2007-06/federationmetadata.xml", // Azure AD元数据URL
        LoadMetadata = true
    });

    // 映射SAML声明到Identity标准声明
    options.ClaimTypeMap[ClaimTypes.Email] = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress";
    options.ClaimTypeMap[ClaimTypes.Name] = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name";
});

var app = builder.Build();

// 配置中间件顺序
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();

app.UseAuthentication();
app.UseSaml2(); // 必须放在UseAuthentication之后、UseAuthorization之前
app.UseAuthorization();

app.MapRazorPages();
app.MapControllers();

app.Run();

4. 添加SAML登录入口

在登录页面(如Login.cshtml)中,添加Azure AD SSO登录按钮:

<form asp-action="Login" method="post">
    <!-- 原有密码登录表单 -->
    <div class="form-group">
        <label asp-for="Email"></label>
        <input asp-for="Email" class="form-control" />
    </div>
    <div class="form-group">
        <label asp-for="Password"></label>
        <input asp-for="Password" class="form-control" type="password" />
    </div>
    <div class="form-group">
        <input asp-for="RememberMe" />
        <label asp-for="RememberMe"></label>
    </div>
    <button type="submit" class="btn btn-primary">密码登录</button>
</form>

<!-- SAML登录按钮 -->
<a href="/saml2/signin" class="btn btn-secondary mt-2">Azure AD SSO登录</a>

5. 处理SAML回调与Identity用户关联

在AccountController中添加外部登录回调逻辑,将SAML认证用户关联到Identity系统:

[HttpGet]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
{
    if (remoteError != null)
    {
        ModelState.AddModelError(string.Empty, $"外部提供商错误: {remoteError}");
        return View("Login");
    }

    var loginInfo = await _signInManager.GetExternalLoginInfoAsync();
    if (loginInfo == null)
    {
        return RedirectToAction(nameof(Login));
    }

    // 尝试用外部登录信息直接登录
    var signInResult = await _signInManager.ExternalLoginSignInAsync(
        loginInfo.LoginProvider, 
        loginInfo.ProviderKey, 
        isPersistent: false, 
        bypassTwoFactor: true);

    if (signInResult.Succeeded)
    {
        return LocalRedirect(returnUrl ?? Url.Content("~/"));
    }

    // 若用户不存在,创建新用户并关联外部登录
    var email = loginInfo.Principal.FindFirstValue(ClaimTypes.Email);
    var newUser = new IdentityUser { UserName = email, Email = email };
    var createResult = await _userManager.CreateAsync(newUser);
    
    if (createResult.Succeeded)
    {
        createResult = await _userManager.AddLoginAsync(newUser, loginInfo);
        if (createResult.Succeeded)
        {
            await _signInManager.SignInAsync(newUser, isPersistent: false);
            return LocalRedirect(returnUrl ?? Url.Content("~/"));
        }
    }

    foreach (var error in createResult.Errors)
    {
        ModelState.AddModelError(string.Empty, error.Description);
    }

    return View("Login");
}

现有密码登录代码兼容

你原有的密码登录逻辑无需修改,可与SAML SSO登录共存:

var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: true);
if (result.Succeeded)
{
    return LocalRedirect(returnUrl ?? Url.Content("~/"));
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 19:35:21