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

如何在ASP.NET Core MVC中实现多项目集中式授权(无需第三方)

ASP.NET Core MVC 集中式认证授权实现方案(无第三方依赖)

方案概述

通过搭建一个基于ASP.NET Core Identity的集中式身份认证服务,让所有业务MVC项目统一对接该服务完成认证授权。以下是最简可运行的实现步骤:


一、集中式身份认证项目配置

1. 修正并完善Program.cs

移除重复的AddAuthorization调用,添加Identity服务和共享Cookie配置:

var builder = WebApplication.CreateBuilder(args);

// 添加MVC控制器与视图支持
builder.Services.AddControllersWithViews();

// 配置Identity与数据库存储
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = false)
    .AddEntityFrameworkStores<ApplicationDbContext>();

// 配置跨项目共享的认证Cookie
builder.Services.ConfigureApplicationCookie(options =>
{
    options.Cookie.Name = ".SharedAuthCookie";
    options.Cookie.Domain = "localhost"; // 本地测试用,生产替换为实际主域名
    options.LoginPath = "/Account/Login";
    options.LogoutPath = "/Account/Logout";
});

// 仅需添加一次授权服务
builder.Services.AddAuthorization();

var app = builder.Build();

// 中间件顺序必须严格遵循:认证在前,授权在后
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages(); // Identity依赖Razor Pages处理默认UI

app.Run();

2. 完善AccountController核心逻辑

补充登录、登出的实现代码:

public class AccountController : Controller
{
    private readonly UserManager<IdentityUser> _userManager;
    private readonly SignInManager<IdentityUser> _signInManager;

    public AccountController(UserManager<IdentityUser> userManager, SignInManager<IdentityUser> signInManager)
    {
        _userManager = userManager;
        _signInManager = signInManager;
    }

    [HttpGet]
    public IActionResult Login(string? returnUrl = null)
    {
        ViewData["ReturnUrl"] = returnUrl;
        return View();
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Login(LoginViewModel model, string? returnUrl = null)
    {
        returnUrl ??= Url.Content("~/");

        if (ModelState.IsValid)
        {
            var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
            if (result.Succeeded) return LocalRedirect(returnUrl);
            
            ModelState.AddModelError(string.Empty, "登录失败,请检查账号密码");
        }
        return View(model);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Logout(string? returnUrl = null)
    {
        await _signInManager.SignOutAsync();
        return LocalRedirect(returnUrl ?? Url.Content("~/"));
    }
}

// 登录视图模型
public class LoginViewModel
{
    [Required]
    [EmailAddress]
    public string Email { get; set; } = string.Empty;

    [Required]
    [DataType(DataType.Password)]
    public string Password { get; set; } = string.Empty;

    [Display(Name = "记住我")]
    public bool RememberMe { get; set; }
}

二、业务MVC项目配置

1. 修正Program.cs配置

配置对接集中式身份服务的认证逻辑,移除重复的AddAuthorization:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews();

// 配置认证服务,使用与身份项目一致的共享Cookie
builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
    options.Cookie.Name = ".SharedAuthCookie";
    options.Cookie.Domain = "localhost";
    // 跳转至集中式身份服务的登录/登出页面
    options.LoginPath = "https://localhost:5001/Account/Login";
    options.LogoutPath = "https://localhost:5001/Account/Logout";
});

// 可选:使用OpenID Connect协议对接(更规范的SSO方案)
// .AddOpenIdConnect(options =>
// {
//     options.Authority = "https://localhost:5001";
//     options.ClientId = "mvc-business-client";
//     options.ClientSecret = "your-client-secret";
//     options.ResponseType = "code";
//     options.SaveTokens = true;
//     options.Scope.Add("openid");
//     options.Scope.Add("profile");
// });

builder.Services.AddAuthorization();

var app = builder.Build();

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

2. 受保护的业务控制器(保持原代码)

public class HomeController : Controller
{
    [Authorize]
    public IActionResult Index()
    {
        return View();
    }
}

核心注意事项

  • 数据保护共享:跨项目共享Cookie时,需确保所有项目使用相同的数据保护密钥,可通过配置文件存储密钥或使用Redis等分布式存储共享。
  • 域名要求:生产环境中,所有项目需部署在同一主域名下(如*.yourdomain.com),确保Cookie可跨子域传递。
  • 方案选择:直接Cookie共享适合小型场景,OpenID Connect协议更安全,支持标准单点登录(SSO),推荐生产环境使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 15:55:02