根据外部身份的角色更新Umbraco用户的用户类型

时间:2015-11-30 17:48:02

标签: c# umbraco umbraco7 identityserver3

在过去的几天里,我一直致力于将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" };
    }   
}

1 个答案:

答案 0 :(得分:0)

在Umbraco服务UserTypeSecurityTokenValidated的帮助下,通过在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错误代码。