2

我有一个需要身份验证算法的基本抽象类。我有两个实现,一个将散列密码并将其与存储的散列进行比较,另一个将使用 Windows 活动目录。

但在实际进行哈希检查或 Windows 身份验证之前,我有绝对必须实现的额外工作流逻辑。因此,无论身份验证的算法如何,都必须始终以相同的方式修改或使用诸如 failedPasswordCount、lastAuthenticationAttemptDate、IsUserApproved 等内容。

在我看来,这个问题似乎可以使用模板方法模式来解决,只是实现我的两种身份验证方法所需的信息因使用的一种而不同。

public abstract class User
{
    public bool Authenticate() // my template method
    {
        lastAuthenticationAttemptDate = DateTime.UtcNow();
        if(IsUserApproved)
        {
            if(DoAuthenticate()) // implemented by childs
            {
                return true;
            }
            else
            {
                failedPasswordCount++;
                return false;
            }
        }
    }

    public abstract DoAuthenticate();
}

public UserWindowsLogon : User
{
    public override bool DoAuthenticate(string windowsDomain, string password)
    {
         ...
    }
}

public UserApplicationLogon : User
{
    public override bool DoAuthenticate(string password)
    {
         ...
    }
}

解决此问题的最佳方法是什么?是否有另一种已知模式已经解决了这个问题?或者任何人有一个好主意?

4

3 回答 3

4

您可以通过这种方式保持基本接口的“DoAuthenticate()”参数干净

public UserWindowsLogon : User
{
    public string windowsDomain;
    public string password;
    public override bool DoAuthenticate()
    {
         // Check and use windowsDomain/password values here
    }
}

或者

public UserApplicationLogon : User
{
    public UserApplicationLogon(string password) : base()
    {
         this.password = password;
    }

    private string password;
    public override bool DoAuthenticate()
    {
         // use password value here
    }
}

并提供实例化用户派生对象时要使用的参数值。

于 2014-05-06T20:22:19.860 回答
3

假设您的客户端代码知道要做什么(应该应用哪些实际参数),您可以轻松地围绕您的身份验证引入类层次结构,从而可以在此类层次结构的基类上声明合同。

public abstract DoAuthenticate( AuthenticationContext context );
...

public UserWindowsLogon : User
{
  public override bool DoAuthenticate( AuthenticationContext context )
  { 
     if ( context is UserWindowsAuthenticationContext )
     {
        // proceed
     }
  }
}

public UserApplicationLogon : User
{
  public override bool DoAuthenticate( AuthenticationContext context )
  {
     if ( context is UserAplicationAuthenticationContext )
     {
        // proceed
     }
   } 
}

public abstract class AuthenticationContext { }

public class UserWindowsAuthenticationContext : AuthenticationContext
{
   public string windowsDomain;
   public string password;
}

public class UserApplicationAuthenticationContext : AuthenticationContext
{
   public string password;
}
于 2014-05-06T20:11:41.907 回答
1

这确实是一个策略模式的示例(其中策略是身份验证/验证机制)遇到复合模式

验证通常是一种复合模式。当你把它分解时,你想把你想做的 事情和你想做的事情分开,会得到:

If foo is valid
then do something.

这里我们的抽象是有效的

我只是在这里写了关于你的案例。如果您发现这个答案最棒,那么也给一个检查/投票 :)

于 2014-05-06T20:59:48.247 回答