示例:
我们有两种用户类型。
它们都与基本相同的数据接口,但一般而言,FactoryUsers可以编辑比SupplierUser更多的此类信息。
使用ASP.NET 4.5,我正在使用MVC实现所有这些。
一些总结用例:(假设已登录)
FactoryUser:
SupplierUser: - 可以查看来自特定工厂的消息。 - 可以创建订单,发送和查看。 - 可以编辑自己的信息
正如您所看到的,这只是通过各种权限进行的大量信息编辑。我的问题是,我应该在哪里开始分离?
关于:
在上面的每一个中,我都可以看到根据用户类型分割逻辑的可能性。但是,当然,我希望以最简单,最理智的方式做到这一点。
是否有某些文件指明了应该如何做,或者其他任何明智的人在此之前做过这件事并遇到所有问题?
由于 (第一个问题!)
答案 0 :(得分:2)
执行此操作的一种方法是创建功能。例如View Orders, Create Order, Update Order, Delete Order
然后会将这些features
分配给Role
- 并且可以将角色分配给User
所以DB看起来像这样:
现在,当用户登录时,您将读取分配给用户的所有功能并将其保存在会话中(创建SessionHandler类)。
// Login Function - You can call from Controller
public UserDTO Login(string username, string password)
{
var user = dbContext.Users.FirstOrDefault(s => s.Username == username && s.Password == password);
if(user == null) return null; // login failed
var model = new UserDTO()
{
UserId = user.UserId,
Features = user.Role.Features.Select(s => s.FeatureName).ToList()
};
return model;
}
UserDTO类的示例
public class UserDTO
{
public int UserId {get;set;}
public List<string> Features {get;set;}
}
SessionHandler
public class SessionHandler
{
private const string SessionKey = "UserSession";
public static UserDTO UserSession
{
get
{
return HttpContext.Current.Session[SessionKey] != null
? (UserDTO)HttpContext.Current.Session[SessionKey]
: null;
}
set { HttpContext.Current.Session[SessionKey] = value; }
}
}
因此,在您的控制器中调用Login
函数并分配到UserSession
中的SessionHandler
[HttpPost]
public ActionResult Login(LoginModel model)
{
var user = Login(model.username, model.password);
if(user == null) return View(model);
SessionHandler.UserSession = user;
// TODO: redirect to Home Page - after login
return RedirectToAction("Index", "Home");
}
然后,您可以在视图中执行的操作是检查用户是否可以执行某项操作,例如如果您在查看订单页面上 - 如果用户没有权限,您可以隐藏创建订单按钮:
@model WhateverDTO
// Check if user has Create Order Feature in Role
@if (SessionHandler.UserSession.Features.Contains("Create Order"))
{
// Yes, User has permission - then Render the Button
<button> Create Order </button>
}
您还可以在Controller(服务器端)中添加检查 - 使用授权属性为您的应用程序提供额外的安全性:
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext == null)
throw new ArgumentNullException("httpContext");
if (httpContext.Session == null)
return false;
// Checking Authenticaiton
var userSettings = SessionHandler.UserSession;
if (userSettings == null)
return true;
//Checking Authorization
if (Roles.Length == 0)
return true;
var actionFeatures = Roles.Split(',');
if (!actionFeatures.Any(s => userSettings.Features.Contains(s)))
throw new UnauthorizedAccessException("You do not have permission to perform this action.");
return true;
}
}
然后装饰你的行动,
[CustomAuthorize(Roles = "Create Order")]
// Pass feature name for Roles - if user doesn't have permission to Create Order - the "You do not have permission to perform this action." exception will get thrown
public ActionResult CreateOrder()
{
return View(new CreateOrderDTO());
}
[HttpPost]
[CustomAuthorize(Roles = "Create Order")]
// Pass feature name for Roles - if user doesn't have permission to Create Order - the "You do not have permission to perform this action." exception will get thrown
public ActionResult CreateOrder(CreateOrderDTO model)
{
return View(model);
}
上述方法的好处是,您可以根据需要添加任意数量的用户角色,而无需更改代码。
模型 - 我认为这个与数据库保持一致
模型相同 - 相同的DB相同模型
ViewModels - 我是否为每个角色编写不同的视图?如果是这样,2个文件/类?
不,不要复杂化 - 使用相同的ViewModel / DTO
控制器 - 同样,我会写不同的功能吗?类?如果是这样,那么具有[授权角色]的重点是保护免受未经授权的访问。不打算拆分?
无需单独的操作/视图或控制器
观点 - 我是否尝试对大多数部分使用相同的视图,并且只是在某种程度上包含了关于他们是否具有&#34;编辑&#34;按钮与否?
是,使用相同的视图 - 根据用户角色/功能隐藏/显示操作
部分视图 - 可以将它们用于&#34;编辑&#34;视图上可能有也可能没有的按钮?
无需按钮的部分视图
查看布局 - ? 过滤器 - 我可以做一些奇特的逻辑并将所有内容放在完全2个不同的文件夹(整个MVC)中,然后在路由/授权级别将其拆分 路由 - ?
没有