多个独立的注册和登录表单.NET Identity 2.0

时间:2016-08-12 15:55:55

标签: c# asp.net asp.net-mvc asp.net-mvc-5 asp.net-identity

在MVC 5中创建一个新项目会启动所有必要的类来处理角色和用户,我可以修改自定义属性。我无法弄清楚的是,在我的场景中,我有多种不同类型的用户,例如主管理员,管理员,作者,供应商和租户。

所有这些都具有不同的属性以及一些共享属性。通常,我会实现每种类型的用户名和用户名。密码在各自的数据库表中。 ASP.NET身份非常诱人,有一种集中的用户存储,其优点是可以通过简单易用的方式管理身份验证,并带有操作结果。

我已阅读谷歌搜索的每一个结果,但与我的方案类似的唯一解决方案是使用声明(据我所知,并非专门用于处理此特定情况)

如果有一种方式asp.net身份支持这种情况,我会徘徊吗?

任何帮助将不胜感激。感谢。

3 个答案:

答案 0 :(得分:2)

作为索赔的替代方案,我会推荐角色。如果您不确定如何阅读,请继续阅读。

如果您使用MVC创建了默认Web应用程序,则已安装Entity Framework。假设您已使用Code首次迁移,那么EF也将为您设置数据库。

在此过程中,它将添加一个文件夹Migrations with class Configuration.cs。此文件包含方法Seed,我们将在其中进行更改。

首先将以下用法添加到Configuration.cs:

using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity;
using Models; // assuming you have kept to the defaults

在种子功能中添加以下代码:

var userStore = new UserStore<ApplicationUser>(context);
var userManager = new UserManager<ApplicationUser>(userStore);
userManager.UserValidator = new UserValidator<ApplicationUser>(userManager) { AllowOnlyAlphanumericUserNames = false };

这里有点小提示。默认情况下,MVC5设置基于电子邮件的用户系统。令人高兴的是,默认情况下,UserManager还会检查UserName(与电子邮件相同)是否包含特殊字符(包括@)。因此需要关闭它。

要添加角色,我们只需:

context.Roles.AddOrUpdate(r => r.Name, new IdentityRole { Name = "MyRoleName" });
context.SaveChanges();  

将新用户添加到角色

if (!context.Users.Any(t => t.Email == "anyone@anywhere.com"))
{
    var user = new ApplicationUser { UserName = "anyone@anywhere.com", Email = "anyone@anywhere.com" };
    userManager.Create(user, "Password#1");
    context.SaveChanges();
    userManager.AddToRole(user.Id, "MyRoleName");
}

将现有用户添加到角色:

var existingUser = context.Users.Where(u => u.UserName == "anyone@anywhere.com").FirstOrDefault();
userManager.AddToRoles(existingUser.Id, "MyRoleName");

要应用这些更改,只需在包管理器窗口中运行update-database。

现在您拥有带角色的用户,您可以使用授权属性限制您喜欢的任何操作:

[Authorize(Roles ="MyRoleName")]

可以在类级别(启用/禁用整个Controller)或单个操作设置这些属性。要设置多个角色,请使用:

[Authorize(Roles ="MyRoleName, MyOtherRole")]

请注意,这意味着任何具有任一角色的人都获得了正式授权。如果您只想授权具有这两种角色的用户,则必须执行以下操作:

[Authorize(Roles ="MyRoleName")]
[Authorize(Roles ="MyOtherRole")]

除了使用角色限制对控制器和操作的访问外,您还可以使用它们来显示/隐藏视图中的项目。例如,使用剃刀:

@if (User.IsInRole("Admin"))
{
   <p><a class="btn btn-danger btn-lg btn-block" href="@Url.Action("Index", "Administration")">Admin Area</a></p>
}

这具有非管理员的优势,用户不会注意到他们缺少的东西!

答案 1 :(得分:1)

您有两种选择来满足您的目的:

  1. 使用共享的ApplicationUser类并分离表单 通过Roles授权。因此,您可以使用if(User.IsInRole("UserTypeName"))基于用户的角色创建带有条件输入的表单(限制使用剃刀中的RoleManager显示的内容),或者为每个用户类型创建单独的视图并在控制器端对其进行授权。
  2. 使用简单继承来实现每个用户类型 属性。
  3. 像:

    public class CustomUser: ApplicationUser
    {
        ...
    }
    

    您最终会在 AspNetUsers 表中找到 Discriminator 列,这将有助于Entity Framework识别它应该为该行实例化哪个类(CustomUserApplicationUser)。然后您可以正常查询,或者如果您只想要一种特定类型,则可以使用OfType<T>之类的:

    var customUsers = db.Users.OfType<CustomUser>();
    

    请记住您添加到继承类的任何属性必须为nullable您无法在数据库级别上要求<{em> DateTime CustomUser之类的内容,因为它会阻止保存ApplicationUser,而不会保存该属性。但是,这只是数据库级别的问题。您仍然可以使用视图模型从前端角度CustomUser required 上创建特定属性。

答案 2 :(得分:0)

首先,我希望您创建所有想要的角色,例如租户等

然后创建像 RegisterViewModel.cs 这样的ViewModel,以便对管理员,租户等进行多次独立注册。

然后使用Controller AccountController.cs 的操作方法注册,如果您希望用户拥有所选角色,您可以使用此单行

    var result = await UserManager.AddToRolesAsync(user.Id, "Tenants");

现在使用像 Register.cshtml 这样的视图来完成流程。

让我用code解释。创建一个ViewModel类Vendor.cs

      public class VendorViewModel
 {
    [Required]
    [EmailAddress]
    [Display(Name = "Email")]
    public string Email { get; set; }

    [Required]
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }}

现在在AccountController.cs中创建一个actionmethod供应商

    [Authorize(Roles = "Admin")]
        public async Task<ActionResult> CreateVendor()
        {

            return View();
        }
         [Authorize(Roles = "Admin")]
           [HttpPost]
 public async Task<ActionResult> Vendor(VendorViewModel model)
        {
            if (ModelState.IsValid)
            {
                var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
                var result = await UserManager.CreateAsync(user, model.Password);
                if (result.Succeeded)
                {
         //Add Vendor role to user
           var role = await UserManager.AddToRolesAsync(user.Id, "Vendor");
 }
                AddErrors(result);
            }

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

现在创建View Vendor.cshtml

          @model IdentitySample.Models.VendorViewModel
@{
    ViewBag.Title = "Vendor";
}

<h2>@ViewBag.Title.</h2>

@using (Html.BeginForm("Vendor", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()
    <h4>Create a new account.</h4>
    <hr />
    @Html.ValidationSummary("", new { @class = "text-danger" })
    <div class="form-group">
        @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.PasswordFor(m => m.Password, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" class="btn btn-default" value="Vendor" />
        </div>
    </div>
}

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

只要您需要这些表单,就可以创建更多类似的内容。