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

.Net Core 3中UseOpenIdConnectAuthentication等效用法及声明添加

解答

问题1:.NET Core 3中UseOpenIdConnectAuthentication的等效实现

ASP.NET Core 3 没有和.NET Framework 4同名的UseOpenIdConnectAuthentication扩展方法,对应能力通过OpenID Connect认证服务+事件回调实现,执行时机和原有逻辑完全一致:

  • 首先通过NuGet安装Microsoft.AspNetCore.Authentication.OpenIdConnect包
  • 在Startup.ConfigureServices中先注册Cookie认证作为本地会话持久化方案,再注册OpenID Connect认证,和你原有先配置Cookie、再配置OIDC的顺序一致
  • 原有代码里SecurityTokenValidated通知的等效逻辑,写在OIDC配置的Events节点下的OnTokenValidated委托中即可,这个委托会在AAD返回的安全令牌校验通过、用户身份初步构建完成后立刻触发,正好适合做用户数据拉取、权限初始化这类操作
  • 原有AuthenticationFailed通知对应OnAuthenticationFailed委托,逻辑可以直接迁移
  • 最后在Startup.Configure中按顺序调用app.UseAuthentication()、app.UseAuthorization()即可,不需要单独注册Use开头的OIDC中间件。

问题2:基于已认证身份添加自定义声明

自定义声明的逻辑直接放在上面提到的OnTokenValidated事件中处理即可,操作流程:

  1. 从事件参数的Principal属性拿到AAD返回的已认证用户身份,提取用户唯一标识(一般用AAD返回的oid声明,也就是用户对象ID)
  2. 用这个唯一标识查询你自己维护的用户、角色数据表,拿到对应用户的角色、权限、业务属性数据
  3. 从用户身份中拿到ClaimsIdentity实例,调用AddClaim方法把查询到的角色、权限等自定义声明逐个添加进去
  4. 事件执行完成后,这些声明会被自动加密写入本地认证Cookie,后续请求会自动携带,不需要重复查询数据库。

参考实现代码

// Startup.cs ConfigureServices 方法配置
public void ConfigureServices(IServiceCollection services)
{
    // 其余业务服务注册逻辑保持原有即可
    services.AddAuthentication(options =>
        {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
        })
        .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
        {
            // 此处可配置Cookie过期时间、登录跳转路径等规则,和.NET4中Cookie配置逻辑一致
        })
        .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
        {
            options.ClientId = "替换为你的AAD应用ClientId";
            options.Authority = "替换为你的AAD实例地址";
            options.CallbackPath = "/signin-oidc"; // 对应原有配置中的RedirectUri路径
            // 其余AAD对接参数按实际场景补充即可

            options.Events = new OpenIdConnectEvents
            {
                // 对应原有AuthenticationFailed逻辑
                OnAuthenticationFailed = context =>
                {
                    context.Response.Redirect("/Home/Error");
                    context.HandleResponse();
                    return Task.CompletedTask;
                },
                // 对应原有SecurityTokenValidated逻辑:令牌校验通过后执行
                OnTokenValidated = async context =>
                {
                    var claimsIdentity = (ClaimsIdentity)context.Principal.Identity;
                    // 提取AAD返回的用户唯一标识
                    var userAadId = claimsIdentity.FindFirstValue("http://schemas.microsoft.com/identity/claims/objectidentifier");
                    
                    // 查询本地用户、角色数据,替换成你自己的DbContext即可
                    var dbContext = context.HttpContext.RequestServices.GetRequiredService<YourAppDbContext>();
                    var appUser = await dbContext.Users.FirstOrDefaultAsync(u => u.AadObjectId == userAadId);
                    if (appUser == null)
                    {
                        // 本地无对应用户时可按需求做自动注册或拒绝访问处理
                        context.Response.Redirect("/Account/AccessDenied");
                        context.HandleResponse();
                        return;
                    }
                    
                    // 添加自定义声明
                    claimsIdentity.AddClaim(new Claim(ClaimTypes.Name, appUser.DisplayName));
                    // 批量添加角色声明
                    var userRoles = await dbContext.UserRoles
                        .Where(r => r.UserId == appUser.Id)
                        .Select(r => r.RoleCode)
                        .ToListAsync();
                    foreach (var role in userRoles)
                    {
                        claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, role));
                    }
                    // 其余业务声明按相同方式添加即可
                }
            };
        });
    
    services.AddControllersWithViews();
}

// Startup.cs Configure 方法配置
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // 其余中间件配置保持原有即可
    app.UseStaticFiles();
    app.UseRouting();
    // 注意认证、授权中间件顺序不能调换
    app.UseAuthentication();
    app.UseAuthorization();

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

注意:如果你的自定义声明数据量较大,不要全部存在Cookie中,避免超过浏览器单Cookie大小限制。这种场景可以只在Cookie中存储用户ID,后续通过IClaimsTransformation接口或者自定义中间件动态加载权限声明即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 18:24:35