将用户添加到ASP.NET Identity角色

44

我知道新的会员包括一个“简单角色提供程序”。

我找不到任何关于在创建用户时分配角色的帮助。我已经添加了一个用户,正确地在DB上创建了表格。我看到了AspNetRolesAspNetUserRolesAspNetUsers表格。

我想把AspNetRoles中的角色分配给AspNetUsers中的一个用户,其中角色/用户的ID将存储在AspNetUserRoles中。

当我创建用户时,我陷入了编程的困境。

我有一个下拉列表来选择角色,但使用Entity CF以及新的ASP.NET身份模型,我不确定如何获取从下拉列表中选择的值的ID和UserID并分配角色。


1
只是想知道您是如何获取角色列表并将其放入下拉菜单中的?您是在询问身份验证还是仅使用已知角色列表? - physics90
1
自从我发布这个以来,Asp.Net Identity已经升级了,我相信他们的网站上有相关信息。抱歉我没有链接。 - Brad Martin
7个回答

73

我在这里找到了一个好答案:Adding Role dynamically in new VS 2013 Identity UserManager

但是,为了提供一个示例以供检查,我将分享一些默认代码。

首先确保您已插入角色。

enter image description here

其次,在用户注册方法上测试它。

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
    if (ModelState.IsValid)
    {
        var user = new ApplicationUser() { UserName = model.UserName  };

        var result = await UserManager.CreateAsync(user, model.Password);
        if (result.Succeeded)
        {
            var currentUser = UserManager.FindByName(user.UserName); 

            var roleresult = UserManager.AddToRole(currentUser.Id, "Superusers");

            await SignInAsync(user, isPersistent: false);
            return RedirectToAction("Index", "Home");
        }
        else
        {
            AddErrors(result);
        }
    }

    // If we got this far, something failed, redisplay form
    return View(model);
}

最后你需要从角色下拉列表中以某种方式获取"超级用户(Superusers)"。


3
最佳答案,你会期待超人做得更差吗? - Eric Bishard
1
我能否将这个问题扩展一下,询问是否有一种方法可以在用户注册时向他们显示角色供选择,然后在注册POST操作中将其分配给用户。 - Spionred
我怀疑这是一个修辞问题,但为了讨论的缘故,我会冒险回答并说不 :-) - Spionred
2
在我的测试/实验中,我发现不需要检索currentUser。我只需调用await this.UserManager.AddToRoleAsync(user.Id, "SpecificRole");用户就会被添加到角色中。 - Scott Fraley
1
非常感谢!在使用您的解决方案之前,我曾经苦苦思索很久! - Alexander
显示剩余2条评论

29

我也遇到了同样的问题。这是我发现的将用户添加到角色中的解决方案。

internal class Security
{
    ApplicationDbContext context = new ApplicationDbContext();

    internal void AddUserToRole(string userName, string roleName)
    {
        var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));

        try
        {
            var user = UserManager.FindByName(userName);
            UserManager.AddToRole(user.Id, roleName);
            context.SaveChanges();
        }
        catch
        {
            throw;
        }
    }
}

3
在我的AccountController中,我没有使用数据库上下文,所以我使用了"await UserManager.UpdateAsync(currentUser)"代替"context.SaveChanges()"。 - Chuck Krutsinger
我想在控制器上放置业务逻辑不是一个好习惯。@ChuckKrutsinger - Eugene Sukh

13

虽然我赞同其他答案关于 RoleManager 的说法,但我建议考虑通过 Claims 实现授权 (将角色表达为声明)。

从 .NET Framework 4.5 开始,Windows Identity Foundation (WIF) 已完全集成到 .NET Framework 中。

在声明感知的应用程序中,角色由应该在令牌中可用的角色声明类型来表示。当调用 IsInRole() 方法时,会检查当前用户是否具有该角色。

角色声明类型使用以下 URI 表示: "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"

因此,不必使用 RoleManager,您可以从 UserManager "将用户添加到角色",做类似以下的事情:

var um = new UserManager();
um.AddClaimAsync(1, new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", "administrator"));

通过上述代码,您已向用户ID为“1”的用户添加了一个值为“administrator”的角色声明...

如MSFT所建议的那样,声明授权可以简化和提高身份验证和授权流程的性能,每次进行授权时都会消除一些后端查询。

使用声明,您可能不再需要RoleStore。 (AspNetRoles、AspNetUserRoles)


据微软公司建议,声明授权可以简化和提高身份验证和授权过程的性能,每次授权发生时都可以消除一些后端查询。您是否有此主张的来源?(不是故意用双关语 :)) 我认为在令牌创建时角色将被缓存,您需要从存储中读取声明或角色,因此ClaimsStore只会替换RoleStore。 - Sandeep Phadke
经过周末的大量研究,这似乎是事情发展的方向。我认为这是为任何在MVC5 +中进行身份验证的人提供的最佳答案。 - cchamberlain
2
您还可以使用 ClaimTypes.Role 而不是 URL 来指示声明类型。因此,您可以使用以下代码创建角色声明:new Claim(ClaimTypes.Role, "administrator") - Alex

9
你是否正在寻找这样的东西:
RoleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(new MyDbContext()));
var str = RoleManager.Create(new IdentityRole(roleName));

请查看用户身份验证


2
我看到了这个,据我所知是要创建角色。我已经在表格上创建了这些角色。我只是不明白如何在创建用户时将所选下拉值的角色分配给用户。这是一个内部应用程序,“超级用户”将创建用户。因此,我希望允许在同一事件中创建用户并分配角色。如果有什么困惑,请谅解。 - Brad Martin

4
这个对我有用。你可以在AccountController -> Register上看到这个代码。
var user = new JobUser { UserName = model.Email, Email = model.Email };
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
    //add this to add role to user
     await UserManager.AddToRoleAsync(user.Id, "Name of your role");
}

但是角色名称必须存在于您的AspNetRoles表中。


3
下面是使用声明式角色的“创建用户”控制器方法的替代实现。
创建的声明可以与Authorize属性一起使用,例如[Authorize(Roles = "Admin, User.*, User.Create")]。
    // POST api/User/Create
    [Route("Create")]
    public async Task<IHttpActionResult> Create([FromBody]CreateUserModel model)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        // Generate long password for the user
        var password = System.Web.Security.Membership.GeneratePassword(25, 5);

        // Create the user
        var user = new ApiUser() { UserName = model.UserName };
        var result = await UserManager.CreateAsync(user, password);
        if (!result.Succeeded)
        {
            return GetErrorResult(result);
        }

        // Add roles (permissions) for the user
        foreach (var perm in model.Permissions)
        {
            await UserManager.AddClaimAsync(user.Id, new Claim(ClaimTypes.Role, perm));
        }

        return Ok<object>(new { UserName = user.UserName, Password = password });
    }

2

请查看此链接:为用户分配角色。您可以在CreateUserWizard控件中添加一个步骤,并选择角色。

<asp:CreateUserWizard ID="RegisterUserWithRoles" runat="server" 
    ContinueDestinationPageUrl="~/Default.aspx" LoginCreatedUser="False" 
    onactivestepchanged="RegisterUserWithRoles_ActiveStepChanged">
    <WizardSteps>
        <asp:CreateUserWizardStep ID="CreateUserWizardStep1" runat="server">
        </asp:CreateUserWizardStep>
        <asp:WizardStep ID="SpecifyRolesStep" runat="server" AllowReturn="False" 
            StepType="Step" Title="Specify Roles">
            <h3>Choose the role.</h3>
            <asp:CheckBoxList ID="RoleList" runat="server">
            </asp:CheckBoxList>
        </asp:WizardStep>
        <asp:CompleteWizardStep ID="CompleteWizardStep1" runat="server">
        </asp:CompleteWizardStep>
    </WizardSteps>
</asp:CreateUserWizard>

在代码后台,你将会有:

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        // Reference the SpecifyRolesStep WizardStep 
        WizardStep SpecifyRolesStep = RegisterUserWithRoles.FindControl("SpecifyRolesStep") as WizardStep;

        // Reference the RoleList CheckBoxList 
        CheckBoxList RoleList = SpecifyRolesStep.FindControl("RoleList") as CheckBoxList;

        // Bind the set of roles to RoleList 
        RoleList.DataSource = Roles.GetAllRoles();
        RoleList.DataBind();
    } 
}
protected void RegisterUserWithRoles_ActiveStepChanged(object sender, EventArgs e)
{
    // Have we JUST reached the Complete step? 
    if (RegisterUserWithRoles.ActiveStep.Title == "Complete")
    {
        // Reference the SpecifyRolesStep WizardStep 
        WizardStep SpecifyRolesStep = RegisterUserWithRoles.FindControl("SpecifyRolesStep") as WizardStep;

        // Reference the RoleList CheckBoxList 
        CheckBoxList RoleList = SpecifyRolesStep.FindControl("RoleList") as CheckBoxList;

        // Add the checked roles to the just-added user 
        foreach (ListItem li in RoleList.Items)
        {
            if (li.Selected)
                Roles.AddUserToRole(RegisterUserWithRoles.UserName, li.Text);
        }
    }
}

他问怎么用 ASP .NET身份验证来实现它。 - NoWar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接