在过去的几天里,我一直致力于将Umbraco Backoffice与IdentityServer v3集成。我已经设法达到了这一点,我在外部对用户进行身份验证,并让Umbraco在后台创建一个具有默认用户类型的用户并将其链接到外部帐户。
我接下来要做的就是根据用户的角色更新Umbraco用户类型。我想我找到了一种方法,可以将Umbraco链接到外部帐户,但是如果为用户删除/添加角色,我无法看到任何方式不断更新每次登录的用户类型。
通过分析Umbraco =
中的代码,似乎没有办法进入验证和更新Umbraco一侧数据的过程。
BackOfficeController
似乎如果找到了umbraco登录,那么用户只是登录,没有任何暴露的事件或选项。只有找不到用户,才会开始创建和链接的整个过程,在那里我可以实际对用户属性进行一些更改。
那就是说,有没有办法在每次登录时根据外部服务器的声明实际更新Umbraco用户的用户类型?
Startup类的代码如下所示。
var user = await UserManager.FindAsync(loginInfo.Login);
if (user != null)
{
await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
}
else
{
if (await AutoLinkAndSignInExternalAccount(loginInfo) == false)
{
ViewBag.ExternalSignInError = new[] { "The requested provider (" + loginInfo.Login.LoginProvider + ") has not been linked to to an account" };
}
}
答案 0 :(得分:0)
在Umbraco服务UserType
和SecurityTokenValidated
的帮助下,通过在IExternalLoginService
上手动检查角色声明和Umbraco IUserService
来管理解决此问题。如果组合不正确(例如,声明中没有管理员角色),我会使用Umbraco IUserService
来更新该用户的UserType
Notifications =
new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = async n =>
{
var id = n.AuthenticationTicket.Identity;
var uid = id.FindFirst(ClaimTypes.NameIdentifier);
var givenName = id.FindFirst(ClaimTypes.GivenName);
var familyName = id.FindFirst(ClaimTypes.Surname);
var roles = id.FindAll(ClaimTypes.Role);
var rolesList = roles as IList<Claim> ?? roles.ToList();
if (
!rolesList.Any(
c =>
string.Equals(c.Value, RoleNames.ContentEditor,
StringComparison.InvariantCultureIgnoreCase)))
throw new HttpException(403,
"You do not have any roles configured for the application");
// create new identity and set name and role claim type
var nid = new ClaimsIdentity(
id.AuthenticationType,
ClaimTypes.GivenName,
ClaimTypes.Role);
UpdateUserType(uid.Value, rolesList, applicationConfiguration.AuthorityUrl);
nid.AddClaim(givenName);
nid.AddClaim(familyName);
nid.AddClaims(rolesList);
nid.AddClaim(uid);
nid.AddClaim(id.FindFirst(ClaimTypes.Email));
n.AuthenticationTicket = new AuthenticationTicket(
nid,
n.AuthenticationTicket.Properties);
}
}
private static void UpdateUserType(string uid, IList<Claim> roles, string providerName)
{
var userService = ApplicationContext.Current.Services.UserService;
var oneUser = ApplicationContext.Current.Services.ExternalLoginService.Find(new UserLoginInfo(providerName, uid)).FirstOrDefault();
if (oneUser == null)
return;
var user = userService.GetUserById(oneUser.UserId);
if (user == null)
return;
if (
roles.Any(
r => string.Equals(r.Value, RoleNames.Administrator, StringComparison.InvariantCultureIgnoreCase))
&& !string.Equals(user.UserType.Alias, UmbracoRoleNames.Administrator))
{
SetUserType(user, UmbracoRoleNames.Administrator, userService);
return;
}
if (
roles.Any(
r => string.Equals(r.Value, RoleNames.ContentEditor, StringComparison.InvariantCultureIgnoreCase))
&& !string.Equals(user.UserType.Alias, UmbracoRoleNames.ContentEditor))
{
SetUserType(user, UmbracoRoleNames.ContentEditor, userService);
return;
}
}
private static void SetUserType(Umbraco.Core.Models.Membership.IUser user, string alias, IUserService userService)
{
try
{
user.UserType = userService.GetUserTypeByAlias(alias);
userService.Save(user);
}
catch (Exception e)
{
LogHelper.Error(typeof(ClassName), "Could not update the UserType of a user.", e);
}
}
在这种特定情况下,当某人缺少来自其角色声明的特权时,我不会将UserType
更改回非管理员/非内容编辑器,因为他们之前被过滤掉了一步正在返回403错误代码。