Net Core动态模型绑定

问题描述 投票:0回答:1

我正在尝试构建一个授权系统,不仅基于用户 - >权限 - >角色 - >组,还包括实体 - >属性。

所以我想在post和put请求中限制模型绑定,这样我就可以验证用户有权更新或创建哪些属性,然后让他/她更新或创建实体......否则拒绝请求。

也许它的想法太复杂但我想拥有与某些CMS在线相同的功能。

我正在阅读,也许这可以通过自定义模型Binder解决,我正在学习很多但是,我想知道这是“正确的道路”还是有更快或更好的方法来做到这一点

非常感谢你,我会不断用代码更新我的问题,所以也许可以帮助将来有同样想法的人。

c# authentication asp.net-core authorization
1个回答
0
投票

我正在做同样的事情,我相信完全可以用自定义[Attributes]做到这一点。这是我在动态select语句中完成它的一个小实现:

首先,我有一个自定义属性,它将枚举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);
}
© www.soinside.com 2019 - 2024. All rights reserved.