因此,我知道如何使IdentityServer4应用程序使用具有挑战性的客户端所具有的文化。通过定义
options.Events = new OpenIdConnectEvents
{
OnRedirectToIdentityProvider = context =>
{
context.ProtocolMessage.UiLocales = "pl-PL";
return Task.CompletedTask;
},
}
我可以使IdentityServer4也显示“ pl-PL”中的登录页面。但是,诀窍在于,我允许用户在登录屏幕上更改语言。如何在登录时通知客户文化信息已更改? 目前,我的客户端甚至不显示任何页面,直接进入登录屏幕(因此,从客户端应用程序浏览器直接重定向到IdentityServer4应用程序,用户可以在其中更改其语言)。
答案 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