我正在类库中开发第三方API连接器桥NOT在ASP.NET .
用户级别
API有3个用户级别,比如:
- UserGoer
- UserDoer
- UserMaker
服务限制
每个API操作可以使用一个或多个用户级角色。例如,我们假设操作和可访问的用户级别如下:
- JokerService(可由UserGoer, UserMaker访问)
- PokerService(可由UserGoer, UserDoer访问)
- MokerService(可访问的UserGoer, UserDoer, UserMaker)
如果UserDoer请求JokerService, API返回错误请求。JokerService只对UserGoer和UserMaker可用。所以,我想限制并抛出一个异常。
用户Token结构
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
}
自定义认证属性
public class AuthenticationFilter : Attribute
{
public TokenType[] TokenTypes { get; private set; }
public AuthenticationFilter(params TokenType[] TokenTypes)
{
this.TokenTypes = TokenTypes;
}
}
示例服务
[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);
}
总而言之,JokerService可以被UserGoer和UserMaker执行。UserDoer没有此服务的权限。
正如您看到的AuthenticationFilter
属性的使用,我在构造函数中获得自定义属性,因为我想知道IToken
是什么。如果存在不相关的"用户身份验证令牌";作为参数传递的类型(IToken),程序应该抛出异常。
这是我的解决方案,你认为有什么最好的做法,我的问题?
谢谢你的帮助。
有趣的问题。在建设性批评中,我最初的想法是,特定类通过属性接受的令牌是在编译时决定的,无法更改。但是,权限检查发生在每个对象的构造上。
您可以使用设置tokenTypes
变量的static
构造函数来防止这种情况。静态构造函数总是在实例构造函数之前运行。这也是确保tokenTypes
永远不为空(在没有自定义属性的情况下)的好地方。
同样,通过tokenTypes
的循环可能是一个接受IToken
和tokenTypes
的函数,更重要的是,可能存在于BaseService.cs中。编写一次逻辑将使将来某些需求需要对其进行更改时更容易维护。:)
参见:https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/static-constructors
希望对你有帮助。