【问题标题】:Cache user profile with external authentication .NET Core IdentityServer4使用外部身份验证.NET Core IdentityServer4 缓存用户配置文件
【发布时间】:2017-02-16 02:47:32
【问题描述】:

对整个身份概念的新认识,但我在 Google 上进行了几次搜索,但没有找到我认为合适的回复。

我将 .NET Core 1.0.0 与 EF Core 和 IdentityServer 4 (ID4) 一起使用。 ID4 位于单独的服务器上,我在客户端获得的唯一信息是声明。我想访问完整的(扩展的)用户个人资料,最好从 User.Identity 访问。

那么我该如何设置,以便在 User.Identity 中填充 ApplicationUser 模型上的所有属性,而无需每次都发送数据库请求?我希望将信息存储在身份验证缓存中,直到会话结束。

我不想做的是在每个控制器中设置一个查询来获取附加信息。客户端上的所有控制器都将从基本控制器继承,这意味着如果有必要,我可以 DI 一些服务。

提前致谢。

客户

app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationScheme = "Cookies"
        });

        app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
        {
            AuthenticationScheme = "oidc",
            SignInScheme = "Cookies",

            Authority = Configuration.GetSection("IdentityServer").GetValue<string>("Authority"),
            RequireHttpsMetadata = false,
            ClientId = "RateAdminApp"
        });

ID4

app.UseIdentity();

app.UseIdentityServer();

services.AddDeveloperIdentityServer()
            .AddOperationalStore(builder => builder.UseSqlServer("Server=localhost;Database=Identities;MultipleActiveResultSets=true;Integrated Security=true", options => options.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name)))
            .AddConfigurationStore(builder => builder.UseSqlServer("Server=localhost;Database=Identities;MultipleActiveResultSets=true;Integrated Security=true", options => options.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name)))
            .AddAspNetIdentity<ApplicationUser>();

应用用户模型

public class ApplicationUser : IdentityUser
{
    [Column(TypeName = "varchar(100)")]
    public string FirstName { get; set; }
    [Column(TypeName = "varchar(100)")]
    public string LastName { get; set; }
    [Column(TypeName = "nvarchar(max)")]
    public string ProfilePictureBase64 { get; set; }
}

【问题讨论】:

    标签: c# asp.net-core asp.net-core-mvc asp.net-identity-3 identityserver4


    【解决方案1】:

    如果您想在身份服务器上转换声明,对于您的情况(您使用 aspnet 身份)覆盖UserClaimsPrincipalFactory 是一种解决方案(请参阅Store data in cookie with asp.net core identity)。

    public class AppClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser, IdentityRole>
    {
        public AppClaimsPrincipalFactory(
            UserManager<ApplicationUser> userManager,
            RoleManager<IdentityRole> roleManager,
            IOptions<IdentityOptions> optionsAccessor) : base(userManager, roleManager, optionsAccessor)
        {
        }
    
        public async override Task<ClaimsPrincipal> CreateAsync(ApplicationUser user)
        {
            var principal = await base.CreateAsync(user);
    
            ((ClaimsIdentity)principal.Identity).AddClaims(new[] {
                 new Claim("FirstName", user.FirstName)
            });
    
            return principal;
        }
    }
    
    // register it
    services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, AppClaimsPrincipalFactory>();
    

    您也可以使用事件(在客户端应用程序上)将额外的声明添加到 cookie 中,它提供声明直到用户注销。

    有两个(可能更多)选项:

    首先使用OnTicketReceived的openidconnect认证:

        app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
        {
            AuthenticationScheme = "oidc",
            SignInScheme = "Cookies",
    
            Authority = Configuration.GetSection("IdentityServer").GetValue<string>("Authority"),
            RequireHttpsMetadata = false,
            ClientId = "RateAdminApp",
            Events = new OpenIdConnectEvents
            {
               OnTicketReceived = e =>
               {
                   // get claims from user profile
                   // add claims into e.Ticket.Principal
                   e.Ticket = new AuthenticationTicket(e.Ticket.Principal, e.Ticket.Properties, e.Ticket.AuthenticationScheme);
    
                   return Task.CompletedTask;
                }
            }
        });
    

    或使用OnSigningIn cookie 认证事件

    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
         AuthenticationScheme = "Cookies",
         Events = new CookieAuthenticationEvents()
         {
             OnSigningIn = async (context) =>
             {
                 ClaimsIdentity identity = (ClaimsIdentity)context.Principal.Identity;
                 // get claims from user profile
                 // add these claims into identity
             }
         }
    });
    

    有关客户端应用程序的解决方案,请参见类似问题:Transforming Open Id Connect claims in ASP.Net Core

    【讨论】:

    • 所以我希望用户配置文件拥有的任何其他属性都需要添加为声明、预定义或自定义?例如。那么在 ApplicationUser 模型上使用 FirstName 真的不会提供任何价值吗?
    • 您想在身份服务器中添加声明吗?查看我的更新。
    • 看起来似乎越来越接近我所追求的了!我对重复属性的唯一担心是我需要确保用户的声明和 AspNetUsers 属性都需要同步。但是我是否可以使用 OnSigningIn 来代替将所有属性选择到 context.Principal.Identity 中,这样可以避免确保声明和 AspNetUsers 属性不同步? @adem-caglin
    猜你喜欢
    • 2019-04-12
    • 2018-06-13
    • 2018-07-19
    • 1970-01-01
    • 2018-06-15
    • 2020-02-09
    • 2021-07-21
    • 1970-01-01
    • 2019-12-22
    相关资源
    最近更新 更多