将“ ui_locale”返回给客户端

时间:2020-08-02 12:25:08

标签: asp.net-core identityserver4

因此,我知道如何使IdentityServer4应用程序使用具有挑战性的客户端所具有的文化。通过定义

options.Events = new OpenIdConnectEvents
{
   OnRedirectToIdentityProvider = context =>
   {
      context.ProtocolMessage.UiLocales = "pl-PL";
      return Task.CompletedTask;
   },                     
}

我可以使IdentityServer4也显示“ pl-PL”中的登录页面。但是,诀窍在于,我允许用户在登录屏幕上更改语言。如何在登录时通知客户文化信息已更改? 目前,我的客户端甚至不显示任何页面,直接进入登录屏幕(因此,从客户端应用程序浏览器直接重定向到IdentityServer4应用程序,用户可以在其中更改其语言)。

1 个答案:

答案 0 :(得分:0)

似乎这不是IdentityServer4提供的功能(欢迎任何矛盾的评论)。因此,我最终使用声明将文化信息传递回客户。 因此,我创建了一个继承自IProfileService的类,以便可以将其他声明JwtClaimTypes.Locale加载到idToken中。但是,似乎在运行时,它所处的环境与其所运行的用户所处的环境不同,因此CultureInfo.CurrentCulture被设置为与我期望的语言环境不同的语言环境(例如,将UI设置为{{1} },但在个人资料服务中,它设置为pl-PL)。因此,我最终创建了一个en-US类,该类基本上是一个包装的InMemoryUserInfo,其中包含我的用户ID和一个包含用户所选语言环境的对象。每当用户更改首选语言或从数据库传递用户语言时,我都会创建该字典的条目/更新。无论如何,ConcurrentDictionary然后被注入到我的个人资料服务中,并在其中添加为另一个声明:

InMemoryUserInfo

记住要向DI注册public class IdentityWithAdditionalClaimsProfileService : IProfileService { private readonly IUserClaimsPrincipalFactory<ApplicationUser> _claimsFactory; private readonly UserManager<ApplicationUser> _userManager; /// <summary> /// This services is running in a different thread then UI, so /// when trying to obtain CultureInfo.CurrentUICulture, it not necessarily /// is going to be correct. So whenever culture is changed, /// it is stored in InMemoryUserInfo. Current user's culture will /// be included in a claim. /// </summary> private readonly InMemoryUserInfo _userInfo; public IdentityWithAdditionalClaimsProfileService( IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory, UserManager<ApplicationUser> userManager, InMemoryUserInfo userInfo) { _claimsFactory = claimsFactory; _userManager = userManager; _userInfo = userInfo; } public async Task GetProfileDataAsync(ProfileDataRequestContext context) { var sub = context.Subject.GetSubjectId(); var user = await _userManager.FindByIdAsync(sub); var principal = await _claimsFactory.CreateAsync(user); var claims = principal.Claims.ToList(); claims = claims.Where(claim => context.RequestedClaimTypes.Contains(claim.Type)).ToList(); claims.Add(new Claim(JwtClaimTypes.Locale, _userInfo.Get(user.Id).Culture ?? throw new ArgumentNullException())); context.IssuedClaims = claims; } public async Task IsActiveAsync(IsActiveContext context) { var sub = context.Subject.GetSubjectId(); var user = await _userManager.FindByIdAsync(sub); context.IsActive = user != null; } }

IProfileService

然后,在我的客户启动时,我分析services.AddTransient<IProfileService, IdentityWithAdditionalClaimsProfileService>(); 中的声明,并将cookie设置为从IdentityServer接收到的区域性:

OpenIdConnectEvents