我正在尝试建立一个不仅基于用户的授权系统 - >权限 - >角色 - >群体,但也在实体 - >属性。
所以我想在post和put请求中限制模型绑定,这样我就可以验证用户有权更新或创建哪些属性,然后让他/她更新或创建实体......否则拒绝请求。
也许这个想法过于复杂,但我想拥有与某些CMS在线相同的功能。
我正在阅读,也许这可以通过自定义模型Binder解决,我正在学习很多但是,我想知道这是“正确的道路”还是可能有更快或更好的方法它
非常感谢你,我会不断用代码更新我的问题,所以也许可以帮助将来有同样想法的人。
答案 0 :(得分:0)
我正在做同样的事情,我相信完全有可能使用自定义[Attributes]
执行此操作。这是我在动态选择语句中完成它的一个小实现:
首先,我有一个自定义属性,它将枚举UserRoles作为输入:
[AttributeUsage(AttributeTargets.Property)]
public class RestrictUserRoles : Attribute
{
public RestrictUserRoles(UserRoles roles)
{
Roles = roles;
}
public UserRoles Roles { get; }
}
UserRoles-enum可以这样实现:
[Flags]
public enum UserRoles
{
[Description("Administrator")]
Admin = 1,
[Description("Employee")]
Employee = 2,
[Description("Head of a division")]
DivisionHead = 4,
[Description("Fired")]
Fired = 8
}
我使用枚举,因为有些员工可能是管理员,部门负责人(甚至被解雇)。
然后我有一个IQueryable扩展,它获取用户有权查看的所有属性,并将这些属性与所选属性相交。为此,我使用动态Linq和反射。
public static class QueryableExtensions
{
public static IQueryable SelectProperties<T>(this IQueryable<T> source, UserRoles roles, string criteria)
{
// get all the properties that a user is authorized to see
var authenticatedProperties = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(prop => prop.CustomAttributes.Any(attr =>
attr.AttributeType == typeof(RestrictUserRoles) &&
(((RestrictUserRoles) Attribute.GetCustomAttribute(prop, typeof(RestrictUserRoles))).Roles & roles) !=
0))
.Select(prop => prop.Name)
.ToList();
// if there aren't any, then the user is not
// authorized to view any properties
// DISCLAIMER: or someone has forgotten to mark any properties
// with the RestrictUserRoles-attribute
if (!authenticatedProperties.Any()) throw new UnauthorizedAccessException();
// we get all the properties that the user wants to
// select from the string that was passed to the function in
// the form Prop1, Prop2, Prop3
var selectProperties = criteria
.Split(',')
.Select(property => property.Trim());
// Get the intersection between these properties, IE we
// select only those properties that the user has selected
// AND is authorized to view
var properties = authenticatedProperties
.Intersect(selectProperties)
.ToList();
// if there are none that intersect, return all those
// properties that a user is authorized to view
if (!properties.Any()) properties = authenticatedProperties;
// run the query using dynamic linq
return source.Select("new(" + properties.JoinToString(",") + ")");
}
}
这不是经过现场测试的,但它应该可以解决这个问题并且很容易扩展到突变。
编辑:忘了我使用扩展函数来加入我在下面定义的所有属性:
public static string JoinToString(this IEnumerable<string> list, string delimiter = "")
{
return string.Join(delimiter, list);
}