1

我有一个应用程序,用户使用 Azure AD 登录,然后将详细信息存储在数据库中。现在,如果用户存在于数据库中,他们将被分配一个角色。这个角色被添加到 startup.cs 中的声明中,这一切都很好。但是,当用户未存储在数据库中并且需要创建时。那么问题是我如何设法使用 UserController.cs 中的用户角色更新 cookie

这是我的 startup.cs ConfigurationService()

        services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
            .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"));

        services.AddControllersWithViews(options =>
        {
            var policy = new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .Build();
            options.Filters.Add(new AuthorizeFilter(policy));
        });
        services.AddRazorPages()
             .AddMicrosoftIdentityUI();

对于存储在数据库中的用户,这是将角色添加到声明的位置

        app.Use((context, next) =>
        {
            var userId = context.User.Identity.Name;
            if (userId == null)
            {
                return next();
            }

            var userService = context.RequestServices.GetRequiredService<IUserService>();

            if (!userService.DoesUserExist())
                return next();

            var roles = userService.GetUser().Role.Type;

            if (!string.IsNullOrEmpty(roles))
            {
                context.User.Identities.FirstOrDefault().AddClaim(new Claim(ClaimTypes.Role, roles));
            }

            return next();
        });

应用程序端点是

    [HttpGet]
    public IActionResult SignInRequest()
    {
        if (_userService.DoesUserExist())
        {
            return RedirectToAction(nameof(Index), "Bookings");
        }

        return RedirectToAction(nameof(Create));
    }

对于当前未存储在数据库中的用户,他们会在创建视图中显示,他们需要在保存到数据库之前完成一些附加信息。风景

    [HttpGet]
    public IActionResult Create()
    {
        return View(GetNewUser());
    }

获取新用户

private UserVM GetNewUser()
    {
        return new UserVM()
        {
            Id = Guid.NewGuid(),
            Firstname = _claimsPrincipal.Claims.FirstOrDefault(c => c.Type == ClaimTypes.GivenName).Value,
            Lastname = _claimsPrincipal.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Surname).Value,
            Oid = _claimsPrincipal.Claims.FirstOrDefault(c => c.Type == "http://schemas.microsoft.com/identity/claims/objectidentifier").Value,
            Roles = _rolesService.GetRoles().Select(s => new SelectListItem(s.Type, s.Id.ToString())).ToList(),
            Locations = _locationService.GetAllLocations().Select(s => new SelectListItem(s.Name, s.Id.ToString())).ToList(),
            SelectedRole = UserRoles.EmployeeOnly
        };
    }

新用户完成附加信息后。在这里,我想使用角色声明更新身份和 cookie,而无需用户注销并重新登录。

    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult Create(UserVM user)
    {
        //here is where I would like to update the cookie and identity claims
        return RedirectToAction(nameof(Index), "Bookings");
    }

这是我的视图的用户模型

public class UserVM
{
    public Guid Id { get; set; }
    public string Firstname { get; set; }
    public string Lastname { get; set; }
    public int RoleId { get; set; }
    public Guid? LocationId { get; set; }
    public string Oid { get; set; }

    public RolesVM Role { get; set; }

    public LocationVM Location { get; set; }

    [DisplayName("Name")]
    public string FullName 
    {
        get { return $"{Firstname} {Lastname}"; }
        set { FullName = ""; } 
    }

    public List<SelectListItem> Locations { get; set; }
    public List<SelectListItem> Roles { get; set; }

    public string SelectedLocation { get; set; }
    public string SelectedRole { get; set; }
}

还将有一个用户编辑页面,用户可以在其中更改更高级别的用户的角色。有四个主要角色“超级用户、管理、管理员、员工”所有新用户都将被赋予员工角色,直到它被更高级别的人更改。

我试图在谷歌上寻找一些关于这种情况的可靠例子,并且已经指出了 UserManager 和 RoleManager 的方向,但由于之前缺乏使用这些知识的知识,我一直无法让它发挥作用。我已经看到一些使用 IClaimTransformation 但我再次无法使用我找到的唯一示例来使用它。如果有人可以帮助指出需要的步骤或指出我可以使用参考点的好例子,我将不胜感激。

4

1 回答 1

0

经过大量研究,我发现了 ControllerBase.cs 中已经存在的一种方法,称为 SignIn(ClaimsPrincipal principal)。我查看了 MVC 的 github 存储库,发现这将沿堆栈向下调用 httpContext.SignInAsync()。这是我一直希望附加到的方法,以便允许更新 cookie 并将我的 UserController 中所需的方法更新为以下内容。旁注我已经更改了方法的名称

    public IActionResult Welcome(UserVM user)
    {
        if (!ModelState.IsValid)
        {
            user.Locations = GetLocations();
            return View(user);
        }

        user.RoleId = Convert.ToInt32(user.SelectedRole);
        user.LocationId = new Guid(user.SelectedLocation);

        if (!_userService.CreateNewUser(_mapper.Map<Users>(user)))
        {
            ModelState.AddModelError("", "Error creating user");
            user.Locations = GetLocations();
            return View(user);
        }

        var result = SignIn(_claimsPrincipal); //THIS WAS ALL THAT WAS NEEDED

        return RedirectToAction(nameof(Index), "Bookings");
    }
于 2021-10-29T11:39:09.913 回答