认证。课堂设计 [英] Authenticator. Class design
问题描述
大家好!
我有一个基类 AuthenticatorBase ,能够使用不同的身份验证主题登录用户 - 登录&密码和令牌。
类看起来像这样:
Hi everyone!
I have a base class AuthenticatorBase that has ability to log in users with different authentication subjects - login & password and token.
Class looks like this:
public abstract class AuthenticatorBase {
public abstract LogInResult LogIn(object authSubject);
public abstract void LogOut(string sessionKey);
}
使用login& ;;进行身份验证的子类密码
The sub-class that authenticates with login & password
public class BasicAuthenticator : AuthenticatorBase {
public override LogInResult Authenticate(object authSubject) {
LogInData credentials = authSubject as LogInData;
if (DbContext.Security.Authorize(credentials))
...............
}
}
使用令牌进行身份验证的子类
The sub-class that authenticates with token
public class TokenBasedAuthenticator: AuthenticatorBase {
public override LogInResult Authenticate(object authSubject)
{
string token = authSubject as string;
User user;
if (DbContext.Security.LogInWithToken(token, out user))
...........
}
}
我在此代码中不喜欢的是类型 System.Object 的参数 authSubject ,我需要将其强制转换为子类。如果我使用,比如 BasicAuthenticator ,我可能会将无效类型作为参数传递。
我知道我可以制作泛型类型 AuthenticatorBase< TAuthSubject> 并且有两个子类 BasicAuthenticator:AuthenticatorBase< LogInData> 和 TokenBasedAuthenticator :AuthenticatorBase< string> 。但是,如果我需要将它们放在列表中,那么通用类都没有通用接口。
我可以创建一个这样的附加界面:
What I don't like in this code is the parameter authSubject of type System.Object, I need to cast it in sub-classes. If I use, say BasicAuthenticator, I might pass invalid type as parameter.
I know I can make generic type AuthenticatorBase<TAuthSubject> and have two sub-classes BasicAuthenticator: AuthenticatorBase<LogInData> and TokenBasedAuthenticator : AuthenticatorBase<string>. But what if I need to have them in list, both generic classes don't have a common interface.
I could create an additional interface like this:
public interface IAuthenticator {
LogInResult LogIn(object authSubject);
}
public abstract class AuthenticatorBase<tauthsubject>: IAuthenticator {
public abstract LogInResult LogIn(TAuthSubject authSubject);
// implementing interface
LogInResult IAuthenticator.LogIn(object authSubject)
{
return LogIn((TAuthSubject)authSubject);
}
}
现在我可以在列表中存储 IAuthenticator 的实例,但这似乎非常不知所措。什么是摆脱参数 authSubject 作为类型 System.Object 的最佳方法?我想调用它并将正确的类型实例传递给身份验证器,而不必考虑身份验证器接受的正确类型。谢谢
我尝试过:
试图使用我的代码,但我发现它重载
Now I can store instances of IAuthenticator in the list, but this seems to be very overwhelmed. What's the best way to get rid of the parameter authSubject as type System.Object??? I want to call it and pass correct instance of type to authenticators without having to think about correct types that authenticator accepts. Thanks
What I have tried:
Tried to use my code, but I find it overloaded
推荐答案
使用泛型是正确的方法,但是如果将它们添加到集合中就是问题,那么你可以让它们实现一个额外的像这样的界面
Using generics is the right way to go, however if adding them to a collection is the issue then you can make them implement an additional interface like this
public interface IAuthenticatorBase
{
// you don't need to define this here, you could leave this interface
// as an empty token interface
void LogOut(string sessionKey);
}
public abstract class AuthenticatorBase<TAuthSubject> : IAuthenticatorBase
{
public abstract LogInResult LogIn(TAuthSubject authSubject);
public abstract void LogOut(string sessionKey);
}
public class BasicAuthenticator : AuthenticatorBase<LogInData>
{
public override LogInResult LogIn(LogInData authSubject)
{
throw new NotImplementedException();
}
public override void LogOut(string sessionKey)
{
throw new NotImplementedException();
}
}
public class TokenBasedAuthenticator : AuthenticatorBase<string>
{
public override LogInResult LogIn(string authSubject)
{
throw new NotImplementedException();
}
public override void LogOut(string sessionKey)
{
throw new NotImplementedException();
}
}
您将获得IAuthenticatorBase列表
You would then have a list of IAuthenticatorBase
List<IAuthenticatorBase> myAuths = new List<IAuthenticatorBase>();
myAuths.Add(new BasicAuthenticator());
myAuths.Add(new TokenBasedAuthenticator());
foreach (IAuthenticatorBase auth in myAuths)
{
// this is where it gets a bit naff but if you want to
// deal with disparate types in a collection then at some point you
// have to convert them to their concrete versions
if (auth is BasicAuthenticator)
{
BasicAuthenticator basicAuthenticator = auth as BasicAuthenticator;
}
else if (auth is TokenBasedAuthenticator)
{
TokenBasedAuthenticator tokenBasedAuthenticator = auth as TokenBasedAuthenticator;
}
}
这篇关于认证。课堂设计的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!