Cha*_* M. 3 c# linq asp.net-mvc asp.net-identity
对于这样一个普遍的问题一定有一个简单的解决方案,所以我为我的无知提前道歉:
我有一个多用户 Web 应用程序(带有 EF6 的 Asp.net MVC5),允许用户查看和/或修改存储在多个相关表(Company、Csearch、Candidate)中的相关数据。(更多详情请参见下文)。他们不应该看到任何其他数据(例如通过篡改 URL)。
我使用 Asp.net Identity 2.0 进行身份验证,并且也想将其用于上述授权。用户数据存储在标准的 AspNetUser 表中。我仅对身份表和业务表使用一种上下文。
我想我必须使用角色或声明来解决这个问题,但我找不到任何关于如何做到这一点的指导。有人能指出我正确的方向吗?
我目前已经通过向 CompanyController 添加 LINQ 条件来解决它(对于公司模型),但这似乎不是解决问题的非常安全和正确的方法。
public ActionResult Index(int? id, int? csearchid)
{
var companies = db.Companies
.OrderBy(i => i.CompanyName)
.Where(t => t.UserName == User.Identity.Name);
return View(companies);
Run Code Online (Sandbox Code Playgroud)
我的数据模型很简单,我使用 Visual Studio 2017 搭建了它的脚手架,首先通过 EF6 代码,我构建了一个关系数据模型,大致如下:
一个公司可以有多个搜索(一对多)。每个搜索可以有多个候选者(一对多)。一个公司可以有多个登录用户。用户保存在 ASP.Net Identity 生成的 AspNetUsers 表中。
我的公司模型如下:
public class Company
{
public int CompanyID { get; set; }
// Link naar de Userid in Identity: AspNetUsers.Id
[Display(Name = "Username")]
public string UserName { get; set; }
public string CompanyName { get; set;}
public string CompanyContactName { get; set; }
[DataType(DataType.EmailAddress)]
public string CompanyEmail { get; set; }
public string CompanyPhone { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }
//One to Many Navigatie links
public virtual ICollection<Csearch> Csearches { get; set; }
Run Code Online (Sandbox Code Playgroud)
小智 5
一旦识别出用户,您就可以确保该用户只能访问自己的数据。您不能为此使用角色,因为这只会定义访问级别。但您可以使用声明。
开箱即用的存在关注点分离。保持这种分离。您不应该直接查询 Identity 表。为此使用 userManager。也不要使用 Identity 对象作为 ViewModel。你可能会暴露比你想要暴露的更多的东西。如果你保持这种分离,你会发现它实际上要容易得多。
身份上下文包含识别用户的所有数据,业务上下文包含所有业务信息,包括用户信息。您可能认为这是多余的,但登录用户与业务用户确实没有任何共同之处。登录电子邮件地址可能与business.user.emailaddress不同(这两种情况下电子邮件地址的含义是什么?)。还要考虑用户无法(不再)登录的可能性。
根据经验,始终考虑信息是身份的一部分还是业务的一部分。
什么时候需要 ApplicationUser?仅适用于当前用户或管理用户时。查询用户时,请始终使用business.user。因为您需要的所有信息都应该在那里可用。
对于当前用户,添加包含您需要的信息的声明。声明的优点是您不必在每次调用时查询数据库来检索此信息,例如相应的 UserId 和(显示)UserName。
如何添加声明
您可以通过向 AspNetUserClaims 表添加一行来向用户添加声明,而无需扩展 ApplicationUser 类。就像是:
userManager.AddClaim(id, new Claim("UserId", UserId));
Run Code Online (Sandbox Code Playgroud)
登录后,声明将自动添加到 ClaimsIdentity 中。
您还可以为扩展 ApplicationUser 的属性添加声明:
public class ApplicationUser : IdentityUser
{
public int UserId { get; set; }
public string DisplayUserName { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
userIdentity.AddClaim(new Claim("UserId", UserId));
userIdentity.AddClaim(new Claim("DisplayUserName", DisplayUserName));
return userIdentity;
}
}
Run Code Online (Sandbox Code Playgroud)
如何阅读权利要求
在控制器中,您可以使用如下代码读取声明:
var user = (System.Security.Claims.ClaimsIdentity)User.Identity;
var userId = user.FindFirstValue("UserId");
Run Code Online (Sandbox Code Playgroud)
您可以在查询中使用 userId 来过滤当前用户的数据,甚至可以使用business.users 作为检索数据的唯一条目。喜欢db.Users(u => u.Id == userId).Companies.ToList();
请注意,该代码只是一个示例。我没有测试全部。这只是为了给你一个想法。如果有不清楚的地方,请告诉我。
| 归档时间: |
|
| 查看次数: |
7888 次 |
| 最近记录: |