简体   繁体   English

C# 中 Class 库类和函数的自定义属性

[英]Custom Attribute For Class Library Classes and Functions in C#

I'm developing 3rd party API connector bridge in class library NOT in ASP.NET.我正在 class 库而不是ASP.NET 中开发第 3 方 API 连接器桥。

User Levels用户等级

API has 3 user levels, lets say: API 有 3 个用户级别,比方说:

  • UserGoer用户访问者
  • UserDoer用户执行者
  • UserMaker用户制造商

Service Restriction服务限制

Each API operation can work with one or multiple user level roles.每个 API 操作都可以与一个或多个用户级别角色一起使用。 For example, lets assume operations and reachable user levels as follows;例如,假设操作和可达到的用户级别如下;

  • JokerService (reachable by UserGoer, UserMaker) JokerService(可由 UserGoer、UserMaker 访问)
  • PokerService (reachable by UserGoer, UserDoer) PokerService(可由 UserGoer、UserDoer 访问)
  • MokerService (reachable by UserGoer, UserDoer, UserMaker) MokerService(可由 UserGoer、UserDoer、UserMaker 访问)

If UserDoer requests for JokerService, API returns bad request.如果 UserDoer 请求 JokerService,API 返回错误请求。 JokerService is only reachable for UserGoer and UserMaker. JokerService 仅对 UserGoer 和 UserMaker 可用。 So, I want to restrict and throw an exception.所以,我想限制并抛出异常。

User Token Structure用户令牌结构

public interface IToken
{
    string AccessToken { get; set; }

    string RefreshToken { get; set; }
}

public class AuthenticationToken : IToken
{
    [JsonProperty("access_token")]
    public string AccessToken { get; set; }

    [JsonProperty("refresh_token")]
    public string RefreshToken { get; set; }
}


public class UserGoerAuthenticationToken : AuthenticationToken
{
}

public class UserDoerAuthenticationToken : AuthenticationToken
{
}

public class UserMakerAuthenticationToken : AuthenticationToken
{
}

Enum枚举

public enum TokenType
{
    Undefined = 0,
    UserGoer = 1,
    UserDoer = 2,
    UserMaker = 3
}

Customized Authentication Attribute自定义身份验证属性

public class AuthenticationFilter : Attribute
{
    public TokenType[] TokenTypes { get; private set; }

    public AuthenticationFilter(params TokenType[] TokenTypes)
    {
        this.TokenTypes = TokenTypes;
    }
}

Example Service示例服务

[AuthenticationFilter(TokenType.UserGoer, TokenType.UserMaker)]
internal class JokerService : BaseService<JokerEntity>
{
    public JokerService(IToken AuthenticationToken) : base(AuthenticationToken)
    {
        var tokenTypes = 
              (typeof(JokerService).GetCustomAttributes(true)[0] as AuthenticationFilter)
              .TokenTypes;

        bool throwExceptionFlag = true;
        foreach (var item in tokenTypes)
        {
            // Check AuthenticationToken is UserGoer or UserMaker by StartsWith function
            if (AuthenticationToken.GetType().Name.StartsWith(item.ToString()))
            {
                throwExceptionFlag = false;
                break;
            }
        }

        if (throwExceptionFlag)
            throw new Exception("Invalid Authentication Token");
    }

    public JokerEntity Create(RequestModel<JokerEntity> model) => base.Create(model);

    public JokerEntity Update(RequestModel<JokerEntity> model) => base.Update(model);

    public JokerEntity Get(RequestModel<JokerEntity> model) => base.Get(model);

    public List<JokerEntity> List(RequestModel<JokerEntity> model) => base.List(model);
}

In summary, JokerService can be executable by UserGoer and UserMaker.综上所述,JokerService 可以被 UserGoer 和 UserMaker 执行。 UserDoer has no permission for this service. UserDoer 没有此服务的权限。

As you see the the usage of AuthenticationFilter attribute, I'm getting custom attributes in the constructor, because i want to know what IToken is.正如您看到的AuthenticationFilter属性的用法,我在构造函数中获取自定义属性,因为我想知道IToken是什么。 If there is an irrelevant "User Authentication Token" type that is passed as parameter (IToken), program should be throw an exception.如果有一个不相关的“用户身份验证令牌”类型作为参数 (IToken) 传递,程序应该抛出异常。

This is my solution, do you think is there any best practice for my problem?这是我的解决方案,您认为我的问题有什么最佳实践吗?

Thank you for your help.谢谢您的帮助。

Interesting question.有趣的问题。 My initial thought at constructive critique would be that the tokens accepted by a particular class via the attribute is something decided at compile time and is unable to change.我对建设性批评的最初想法是,特定 class 通过属性接受的标记是在编译时决定的,无法更改。 But, the checking for permissions is happening on the construction of each object.但是,权限检查发生在每个 object 的构造上。

You can prevent this with a static constructor that sets the tokenTypes variable.您可以使用设置tokenTypes变量的static构造函数来防止这种情况。 Static constructors always run before instance constructors. Static 构造函数总是在实例构造函数之前运行。 This is also a good place to ensure that tokenTypes is never null (in the absence of your custom attribute).这也是确保tokenTypes永远不会是 null(在没有自定义属性的情况下)的好地方。

Likewise, the looping through tokenTypes can probably be a function that takes in an IToken and the tokenTypes , and more importantly, could probably live in the BaseService.cs.同样,遍历tokenTypes的循环可能是 function,它接受ITokentokenTypes ,更重要的是,可能存在于 BaseService.cs 中。 Writing that logic once will make it easier to maintain when some future requirement necessitates its change.当某些未来的需求需要对其进行更改时,编写一次该逻辑将使它更容易维护。 :) :)

See also: https://learn.microsoft.com/en-us/do.net/csharp/programming-guide/classes-and-structs/static-constructors另请参阅: https://learn.microsoft.com/en-us/do.net/csharp/programming-guide/classes-and-structs/static-constructors

Hope this helps.希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM