处理AuthenticationResult来自同一页面中的不同提供者

时间:2013-04-23 10:33:24

标签: asp.net openid dotnetopenauth asp.net-4.5 liveid

我正在使用LiveID和Google提供商将OpenID集成到我现有的应用程序中。在我的登录页面上,除了原始登录字段外,我还添加了“使用Google登录”和“使用Microsoft登录”按钮。

我可以成功读取上述两个提供商的AuthenticationResult数据,但是按以下方式完成此操作......

对于新的登录按钮,我制作了一个返回URL,以便在用户返回时区分它们:

Protected Sub btn_google_Click(sender As Object, e As EventArgs) Handles btn_google.Click
    Dim client As New GoogleOpenIdClient
    Dim u As New System.Uri("http://www.mytest.com/login.aspx?action=signin&provider=google")
    client.RequestAuthentication(New HttpContextWrapper(HttpContext.Current), u)
End Sub

Protected Sub btn_live_Click(sender As Object, e As EventArgs) Handles btn_live.Click
    Dim client As New MicrosoftClient("xyz", "12345")
    Dim u As New System.Uri("http://www.mytest.com/login.aspx?action=signin&provider=microsoft")
    client.RequestAuthentication(New HttpContextWrapper(HttpContext.Current), u)
End Sub

因此,当用户被重定向回login.aspx时,我会进行以下检查以处理登录功能:

If Not Page.IsPostBack Then
    If Request.QueryString("action") IsNot Nothing AndAlso Request.QueryString("action").Trim = "signin" Then
        If Request.QueryString("provider") IsNot Nothing AndAlso Request.QueryString("provider").Trim <> String.Empty Then
            Select Case Request.QueryString("provider").Trim
                Case "microsoft"
                    Dim client As New MicrosoftClient("xyz", "12345")
                    Dim u As New System.Uri("http://www.mytest.com/loginlive.aspx?action=signin&provider=microsoft")
                    Dim result As DotNetOpenAuth.AspNet.AuthenticationResult = client.VerifyAuthentication(New HttpContextWrapper(HttpContext.Current), u)
                    ' remainder of logic removed
                    ' ...
                Case "google"
                    Dim client As New GoogleOpenIdClient
                    Dim result As DotNetOpenAuth.AspNet.AuthenticationResult = client.VerifyAuthentication(New HttpContextWrapper(HttpContext.Current))
                    ' remainder of logic removed
                    ' ...
            End Select
        End
    End
End If

我的主要问题是,这是处理AuthenticationResults的好方法吗?或者,是否有更好/更安全/更聪明的方法来实现同样的目标?

1 个答案:

答案 0 :(得分:1)

更好的方法是将抽象工厂模式与命令模式结合使用。这可以减少硬编码并使代码松散耦合,因此您可以在将来为每个身份验证提供程序扩展功能。找到下面代码的每个部分的片段

“BaseAuthentication Provider”的抽象类

public abstract class BaseAuthenticationProvider
{
    //abstract Methods that need to be invoked from the concrete class, this need to be decided based on the functionality you need to achieve. This function would be invoked using the command pattern.
    // AuthorizeUser() : this method would be invoked to authorize the user from the provider

   //AuthenticateUser() : this method would be invoked once the user is redirected from the provider site.

    //abstract Properties that will hold the base information for the authentication provider, this need to be decided based on the functionality you need to achieve
    //CustomerSecret
    //CustomerConsumerKey
}

使用以下代码段为Gooogle,Yahoo,Microsoft等实现具体类。

public class GoogleAuthentication : BaseAuthenticationProvider
{
     public GoogleAuthentication()
     {
          //initialization
     }

     public void AuthorizeUser()
     {
          //code
     }

     public string CustomerSecret()
     {
          //code
     }

     public string CustomerConsumerKey()
     {
          //code
     }
}

工厂类创建具体对象,以防止创建此工厂类的实例实现私有构造函数。

public class AuthenticationProviderFactory
{
     private AuthenticationProviderFactory()
     {
     }

     public static BaseAuthenticationProvider GetInstance(string Domain)
     {
          switch (Domain)
          {
               case "google":
                    return new GoogleAuthentication();
               case "yahoo":
                    return new YahooAuthentication();
           }
      }
 }

Login.aspx:为每个身份验证提供程序提供按钮,为每个按钮设置“CommandName”的值,并将所有按钮链接到同一个事件处理程序

例如btn_google.CommandName =“google”

Protected Sub AuthenticationProvider_Click(sender As Object, e As EventArgs) Handles btn_google.Click, btn_yahoo.Click
    AuthenticationProviderFactory.GetInstance(((Button)sender).CommandName).AuthorizeUser();
End Sub

各自的AuthorizeUser方法将调用相应的提供程序站点进行身份验证。当提供者将用户重定向到返回URL时,在Page_Load事件上应用相同的模式,并从抽象类中调用Autheticate方法。