在MVC应用程序中,我想实现一组规则,超级用户可以创建,读取,更新和删除。
每条规则明确允许/禁止用户以以下格式执行操作:
<Allow || Deny> userId <action_key> <condition>
操作键类似"DoSomeAction"
字符串。
然后我打算在控制器内部使用这些规则进行授权 授权。例如:
//GET ViewProduct/id
public ActionResult ViewProduct(string productId)
{
var product = // get product from repository;
if(RulesAuthorizer.Authorise("ViewProduct", User.Identity.GetUserId(), product){
//proceed to product... JSON or partial view, etc.
}
return new HttpStatusCodeResult(403);
}
ViewProduct是上面的示例action_key。
在Authorise(string action_key, string userId, object ruleArg = null)
方法中,我会从数据库加载此操作键的所有用户相关规则,并决定是否允许该用户。
但是,这确实是个问题,我怎么能将规则的条件用作字符串。例如,条件是:
用户必须是该组的成员&#34;客户&#34;并且产品不得属于&#34;奶酪&#34;或
自定义方法结果,例如如果产品是由组X添加的,而组Y必须看不到它,我可以使用我的方法Product.GetAddedBy()并在LINQ表达式中包含此方法。
我如何为每个规则存储字符串条件,然后从它们构建LINQ表达式?
我打算在可选的ruleArg参数中传递有问题的对象(示例中的Product)。
对于存储字符串的方便方法,我们非常感谢任何想法,可以在运行时使用LINQ表达式或任何替代方法,例如可能将地图条件映射到带参数的委托?
答案 0 :(得分:2)
以下是使用字符串通过Attributes进行用户访问以确定他们有权访问的内容的示例。这是使用Action / Controller来确定访问权限,但您可以根据需要修改它。
使用[AuthoriseByRole]
装饰控制器首先是属性
namespace PubManager.Authorisation
{
public class AuthoriseByRoleAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var isAuthorized = base.AuthorizeCore(httpContext);
if (!isAuthorized && httpContext.Request.IsAjaxRequest())
{
httpContext.Response.StatusCode = 401;
httpContext.Response.End();
}
if (isAuthorized)
{
var request = httpContext.Request;
var r = request.RequestContext.RouteData.Values["r"]
?? request["r"];
var currentUser = (UserModel) HttpContext.Current.Session["user"];
if (currentUser == null)
{
currentUser = HttpContext.Current.User.GetWebUser();
}
var rd = httpContext.Request.RequestContext.RouteData;
string currentAction = rd.GetRequiredString("action");
string currentController = rd.GetRequiredString("controller");
if (currentUser.HasAccess(currentController, currentAction))
return true;
}
httpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return false;
}
}
}
然后用于确定访问的UserModel:
namespace PubManager.Domain.Users
{
public class UserModel
{
public int UserId { get; set; }
public string UserName { get; set; }
public string Title { get; set; }
[Required]
[DisplayName("Forename")]
public string FirstName { get; set; }
[Required]
public string Surname { get; set; }
[Required]
[DisplayName("Company name")]
public DateTime? LastLogin { get; set; }
public bool LockedOut { get; set; }
public DateTime? LockedOutUntil { get; set; }
public bool IsGlobalAdmin { get; set; }
public bool? IsSystemUser { get; set; }
public IEnumerable<RoleModel> Roles { get; set; }
public bool HasAccess(string controller, string view)
{
if (IsGlobalAdmin || IsSystemUser.Value)
{
return true;
}
var isAuthorized = false;
if (!Roles.Any())
return false;
foreach (var role in Roles)
{
if (role.PageToRoles == null)
return false;
foreach (var pg in role.PageToRoles)
{
if (pg.RolePage.Controller.Equals(controller, StringComparison.InvariantCultureIgnoreCase) && (pg.RolePage.View.Equals(view, StringComparison.InvariantCultureIgnoreCase) || pg.RolePage.View.Equals("*")))
isAuthorized = true;
}
}
return isAuthorized;
}
}
}
最后GetWebUser类来获取用户
namespace PubManager.Domain.Users
{
public static class SecurityExtensions
{
public static string Name(this IPrincipal user)
{
return user.Identity.Name;
}
public static UserModel GetWebUser(this IPrincipal principal)
{
if (principal == null)
return new UserModel();
var db = new DataContext();
var user = (from usr in db.Users
where usr.UserName == principal.Identity.Name
select new UserModel
{
Title = usr.Person.Title,
UserName = usr.UserName,
FirstName = usr.Person.FirstName,
Surname = usr.Person.LastName,
Email = usr.Person.Email,
LockedOut = usr.LockedOut,
UserId = usr.UserId,
IsSystemUser = usr.IsSystemUser,
IsGlobalAdmin = usr.IsGlobalAdmin.Value,
PersonId = usr.PersonId,
Roles = from r in usr.UserToRoles
select new RoleModel
{
RoleId = r.RoleId,
PageToRoles = from ptr in r.Role.PageToRoles
select new PageToRoleModel
{
RolePage = new RolePageModel
{
Controller = ptr.RolePage.Controller,
View = ptr.RolePage.View
}
}
}
}).FirstOrDefault();
if (user != null)
{
HttpContext.Current.Session["user"] = user;
}
return user;
}
}
}