2017-10-31 6 views
0

私は、ユーザー - 権限 - >役割 - >グループだけでなく、エンティティ - >プロパティに基づいて認証システムを構築しようとしています。Net Core Dynamic Model Binding

私はポストリクエストとプットリクエストのモデルバインドを制限して、ユーザーが更新または作成する権限を持っているかどうかを確認し、エンティティを更新または作成させることができます。 。

多分、複雑すぎるアイデアかもしれませんが、私はいくつかのCMSオンラインと同じ機能を持ちたいと思っていました。

私は読んでいましたが、これはカスタムモデルバインダーで解決できるかもしれませんが、私はそれについて多くのことを学んでいますが、これが正しい道か、もっと速く、それをする

ありがとう、私はコードで私の質問を更新し続けるつもりです、多分、同じアイデアで将来誰かを助けることができます。

答えて

0

私はまったく同じことに取り組んでおり、カスタム[Attributes]でこれを行うことは完全に可能だと思います。ここで私は、動的選択-文でそれをやったかの小さな実装です:

はまず、私は、入力として列挙UserRolesを取るカスタム属性を持っている:

[AttributeUsage(AttributeTargets.Property)] 
public class RestrictUserRoles : Attribute 
{ 
    public RestrictUserRoles(UserRoles roles) 
    { 
     Roles = roles; 
    } 

    public UserRoles Roles { get; } 
} 

UserRoles、列挙型を実装することができます

[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); 
} 
+0

我々はgithubのレポをどのように作成する場合とhttpsを使用して、より簡単に、鉱山を私たちの取り組みを共有:// www.nuget.org/packages/System.Linq.Dynamic.Core/ –

関連する問題