在MVC 5中创建一个新项目会启动所有必要的类来处理角色和用户,我可以修改自定义属性。我无法弄清楚的是,在我的场景中,我有多种不同类型的用户,例如主管理员,管理员,作者,供应商和租户。
所有这些都具有不同的属性以及一些共享属性。通常,我会实现每种类型的用户名和用户名。密码在各自的数据库表中。 ASP.NET身份非常诱人,有一种集中的用户存储,其优点是可以通过简单易用的方式管理身份验证,并带有操作结果。
我已阅读谷歌搜索的每一个结果,但与我的方案类似的唯一解决方案是使用声明(据我所知,并非专门用于处理此特定情况)
如果有一种方式asp.net身份支持这种情况,我会徘徊吗?
任何帮助将不胜感激。感谢。
答案 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)
您有两种选择来满足您的目的:
ApplicationUser
类并分离表单
通过Roles
授权。因此,您可以使用if(User.IsInRole("UserTypeName"))
基于用户的角色创建带有条件输入的表单(限制使用剃刀中的RoleManager
显示的内容),或者为每个用户类型创建单独的视图并在控制器端对其进行授权。像:
public class CustomUser: ApplicationUser
{
...
}
您最终会在 AspNetUsers 表中找到 Discriminator 列,这将有助于Entity Framework识别它应该为该行实例化哪个类(CustomUser
或ApplicationUser
)。然后您可以正常查询,或者如果您只想要一种特定类型,则可以使用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")
}
只要您需要这些表单,就可以创建更多类似的内容。