#title(OpenIDでログインできるサイトを作成する3)

#navi(.NETプログラミング研究)

#contents

*OpenIDでログインできるサイトを作成する3 [#n9c4e07f]

今回もDotNetOpenIdライブラリを使ってOpenIDでログインできるサイトを作成する方法を紹介します。今回は今まで紹介してきたOpenIdLoginコントロール以外のコントロールを使ってみます。

**OpenIdAjaxTextBoxコントロール [#sc53db20]

OpenIdAjaxTextBoxコントロールを使うと、画面の遷移を行わずに、認証を行うことができます。OPの認証ページはポップアップウィンドウで表示されます。OpenIdLoginコントロールとは違い、認証に成功してもRPのWebサイトにログインした状態にはなりません。つまり、もしログインした状態にするには、FormsAuthentication.RedirectFromLoginPageメソッドを呼び出す必要があります。

このコントロールは、例えば、ブログ等のコメント投稿フォームでスパム防止のためにOpenIDの認証を必要とする場合などに使えそうです。

実際にOpenIdAjaxTextBoxコントロールを使ってOpenID認証を行ってみると、次のようになります。

まずOpenIdAjaxTextBoxコントロールにOpenID URLを入力し、その後コントロールからフォーカスが外れると、OPのDiscovery(OP Endpoint URLを探す)が行われます。その間、OpenIdAjaxTextBoxコントロールの右側にクルクル回るアイコンが表示されます。

#embed(<a href="http://www.flickr.com/photos/dobondotnet/3678190573/" title="OpenIdAjaxTextBox2 by DOBON.NET on Flickr"><img src="http://farm3.static.flickr.com/2609/3678190573_dfc2618f05.jpg" width="294" height="24" alt="OpenIdAjaxTextBox2" /></a>)
#embed(<a href="https://www.flickr.com/photos/dobondotnet/3678190573/" title="OpenIdAjaxTextBox2 by DOBON.NET on Flickr"><img src="https://farm3.static.flickr.com/2609/3678190573_dfc2618f05.jpg" width="294" height="24" alt="OpenIdAjaxTextBox2" /></a>)

Discoveryに成功すると、左側にOPのアイコンが表示され、右側に「LOG IN」ボタンが表示されます。Discoveryに失敗したときは、「LOG IN」ボタンの代わりに「RETRY」ボタンが表示されます。

#embed(<a href="http://www.flickr.com/photos/dobondotnet/3678190589/" title="OpenIdAjaxTextBox3 by DOBON.NET on Flickr"><img src="http://farm3.static.flickr.com/2593/3678190589_2b5fee4c0a.jpg" width="294" height="24" alt="OpenIdAjaxTextBox3" /></a>)
#embed(<a href="https://www.flickr.com/photos/dobondotnet/3678190589/" title="OpenIdAjaxTextBox3 by DOBON.NET on Flickr"><img src="https://farm3.static.flickr.com/2593/3678190589_2b5fee4c0a.jpg" width="294" height="24" alt="OpenIdAjaxTextBox3" /></a>)

「LOG IN」ボタンをクリックするとポップアップウィンドウが表示され、OPの認証ページが表示されます。

認証に成功すると、OpenIdAjaxTextBoxコントロールの右側にチェックマークが付きます。

#embed(<a href="http://www.flickr.com/photos/dobondotnet/3678190633/" title="OpenIdAjaxTextBox5 by DOBON.NET on Flickr"><img src="http://farm4.static.flickr.com/3621/3678190633_8620bdc62c.jpg" width="294" height="24" alt="OpenIdAjaxTextBox5" /></a>)
#embed(<a href="https://www.flickr.com/photos/dobondotnet/3678190633/" title="OpenIdAjaxTextBox5 by DOBON.NET on Flickr"><img src="https://farm4.static.flickr.com/3621/3678190633_8620bdc62c.jpg" width="294" height="24" alt="OpenIdAjaxTextBox5" /></a>)

認証に成功すると、OpenIdAjaxTextBoxコントロールのAuthenticationResponse.StatusプロパティがAuthenticationStatus.Authenticatedになります。

以下に、OpenIdAjaxTextBoxコントロールを使った例を示します。この例では、OpenIDでログインしないとコメントの書き込みができないようにしています(ただし、実際には書き込みを行っていません)。

#code(vbnet){{
<%@ Page Language="vb" %>

<%@ Register assembly="DotNetOpenId" namespace="DotNetOpenId.RelyingParty"
 tagprefix="RP" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
    
    Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs)
        '認証に成功しているか調べる 
        If OpenIdAjaxTextBox1.AuthenticationResponse IsNot Nothing AndAlso _
                OpenIdAjaxTextBox1.AuthenticationResponse.Status = _
                    AuthenticationStatus.Authenticated Then
            '書き込みに成功したことにする(テストなので、そのふりだけ) 
            Dim ci As String = _
                OpenIdAjaxTextBox1.AuthenticationResponse.ClaimedIdentifier
            MessageLabel.Text = Server.HtmlEncode(ci) + _
                "さんはコメントを書き込みました。"
        Else
            MessageLabel.Text = "ログインしてください。"
        End If
    End Sub
    
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>OpenIDテスト</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Label ID="Label1" runat="server"
            AssociatedControlID="OpenIdAjaxTextBox1" 
            EnableViewState="False" Text="OpenID:"></asp:Label>
        <br />
        <RP:OpenIdAjaxTextBox ID="OpenIdAjaxTextBox1" runat="server" />
        <br />
        <asp:Label ID="Label2" runat="server"
            AssociatedControlID="TextBox2"
            EnableViewState="False" Text="お名前:"></asp:Label>
        <br />
        <asp:TextBox ID="TextBox2" runat="server" Width="300px"></asp:TextBox>
        <br />
        <asp:Label ID="Label3" runat="server" AssociatedControlID="TextBox1" 
            EnableViewState="False" Text="コメント:"></asp:Label>
        <br />
        <asp:TextBox ID="TextBox1" runat="server" Height="100px"
            TextMode="MultiLine" Width="300px" EnableViewState="False">
        </asp:TextBox>
        <br />
        <asp:Button ID="Button1" runat="server" Text="送信"
            onclick="Button1_Click" />
        <br />
        <br />
        <asp:Label ID="MessageLabel" runat="server" EnableViewState="False">
        </asp:Label>
    </div>
    </form>
</body>
</html>
}}

#code(csharp){{
<%@ Page Language="C#" %>

<%@ Register assembly="DotNetOpenId" namespace="DotNetOpenId.RelyingParty"
 tagprefix="RP" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

    protected void Button1_Click(object sender, EventArgs e)
    {
        //認証に成功しているか調べる
        if (OpenIdAjaxTextBox1.AuthenticationResponse != null &&
            OpenIdAjaxTextBox1.AuthenticationResponse.Status ==
                AuthenticationStatus.Authenticated)
        {
            //書き込みに成功したことにする(テストなので、そのふりだけ)
            string ci = OpenIdAjaxTextBox1.AuthenticationResponse.ClaimedIdentifier;
            MessageLabel.Text = Server.HtmlEncode(ci) +
                "さんはコメントを書き込みました。";
        }
        else
        {
            MessageLabel.Text = "ログインしてください。";
        }
    }

</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>OpenIDテスト</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Label ID="Label1" runat="server"
            AssociatedControlID="OpenIdAjaxTextBox1" 
            EnableViewState="False" Text="OpenID:"></asp:Label>
        <br />
        <RP:OpenIdAjaxTextBox ID="OpenIdAjaxTextBox1" runat="server" />
        <br />
        <asp:Label ID="Label2" runat="server"
            AssociatedControlID="TextBox2"
            EnableViewState="False" Text="お名前:"></asp:Label>
        <br />
        <asp:TextBox ID="TextBox2" runat="server" Width="300px"></asp:TextBox>
        <br />
        <asp:Label ID="Label3" runat="server" AssociatedControlID="TextBox1" 
            EnableViewState="False" Text="コメント:"></asp:Label>
        <br />
        <asp:TextBox ID="TextBox1" runat="server" Height="100px"
            TextMode="MultiLine" Width="300px" EnableViewState="False">
        </asp:TextBox>
        <br />
        <asp:Button ID="Button1" runat="server" Text="送信"
            onclick="Button1_Click" />
        <br />
        <br />
        <asp:Label ID="MessageLabel" runat="server" EnableViewState="False">
        </asp:Label>
    </div>
    </form>
</body>
</html>
}}

***JavaScriptでClaimed Identifierや個人情報を表示する [#f90a6f51]

OpenIdAjaxTextBoxコントロールでは、認証後、画面遷移なしで(JavaScriptで)Claimed Identifierを表示することができます。それには、そのためのJavaScriptを書き、OpenIdAjaxTextBoxのOnClientAssertionReceivedプロパティで実行するJavaScriptを指定します。

例えば、JavaScriptで次のようなコードを書きます。ここでは、TextBox2にClaimed Identifierを表示しようとしています。

#code(javascript){{
<script type="text/javascript">
    function onauthenticated(sender) {
        var name = document.getElementById('<%=TextBox2.ClientID%>');
        if (sender) {
            //sender.getClaimedIdentifier()でClaimed Identifierを取得
            name.value = sender.getClaimedIdentifier();
        }
    }
</script>
}}

そして、OpenIdAjaxTextBoxコントロールのOnClientAssertionReceivedプロパティを"onauthenticated(sender)"とすると、認証後にTextBox2にClaimed Identifierが表示されるようになります。

JavaScriptのコードで"sender"には、"openid_identifier"という名前のInputボックス(OpenIdAjaxTextBoxコントロールのInputボックス)が入ります。また、sender.getClaimedIdentifier()でClaimed Identifierを取得することができます。

さらに同じようなやり方で、SREGで取得した個人情報を画面遷移なしで表示することもできます。それにはさらに、OpenIdAjaxTextBoxコントロールのUnconfirmedPositiveAssertionイベントハンドラでRegisterClientScriptExtensionメソッドを呼び出します。

DotNetOpenIdのヘルプのOpenIdAjaxTextBox.OnClientAssertionReceivedプロパティの説明によると、認証が確認されなくてもこのJavaScriptが実行されてしまうため、セキュリティ的に重要なコードは書いてはいけないということです。実際に認証が確認されるのは、OpenIdAjaxTextBox.LoggedInイベントが発生したときです。

個人情報をJavaScriptで表示する具体例はDotNetOpenIdに添付されているサンプルにありますが、以下にも紹介しておきます。この例では、ユーザーのニックネームを取得できればTextBox2に表示し、できなければClaimed Identifierを表示しています。

#code(vbnet){{
<%@ Page Language="vb" %>

<%@ Register assembly="DotNetOpenId" namespace="DotNetOpenId.RelyingParty"
 tagprefix="RP" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
    
    Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs)
        '認証に成功しているか調べる 
        If OpenIdAjaxTextBox1.AuthenticationResponse IsNot Nothing AndAlso _
                OpenIdAjaxTextBox1.AuthenticationResponse.Status = _
                    AuthenticationStatus.Authenticated Then
            '書き込みに成功したことにする(テストなので、そのふりだけ) 
            Dim ci As String = OpenIdAjaxTextBox1.AuthenticationResponse.ClaimedIdentifier
            MessageLabel.Text = Server.HtmlEncode(ci) & "さんはコメントを書き込みました。"
        Else
            MessageLabel.Text = "ログインしてください。"
        End If
    End Sub

    Protected Sub OpenIdAjaxTextBox1_LoggingIn(ByVal sender As Object, _
                                               ByVal e As OpenIdEventArgs)
        'ニックネームを要求する 
        Dim cr As New DotNetOpenId.Extensions.SimpleRegistration.ClaimsRequest()
        cr.PolicyUrl = New Uri(Request.Url, Response.ApplyAppPathModifier( _
                               "~/PrivacyPolicy.aspx"))
        cr.Nickname = DotNetOpenId.Extensions.SimpleRegistration.DemandLevel.Request
        e.Request.AddExtension(cr)
    End Sub

    Protected Sub OpenIdAjaxTextBox1_UnconfirmedPositiveAssertion( _
            ByVal sender As Object, ByVal e As OpenIdEventArgs)
        OpenIdAjaxTextBox1.RegisterClientScriptExtension( _
            Of DotNetOpenId.Extensions.SimpleRegistration.ClaimsResponse)("sreg")
    End Sub
    
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>OpenIDテスト</title>

<script type="text/javascript">
    function onauthenticated(sender) {
        var name = document.getElementById('<%=TextBox2.ClientID%>');
        if (sender) {
            if (sender.sreg && sender.sreg.nickname) {
                //個人情報(ニックネーム)を表示する
                name.value = sender.sreg.nickname;
            } else {
                //Claimed Identifierを表示する
                name.value = sender.getClaimedIdentifier();
            }
        }
    }
</script>

</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Label ID="Label1" runat="server" AssociatedControlID="OpenIdAjaxTextBox1" 
            EnableViewState="False" Text="OpenID:"></asp:Label>
        <br />
        <RP:OpenIdAjaxTextBox ID="OpenIdAjaxTextBox1" runat="server" 
            onunconfirmedpositiveassertion=
                "OpenIdAjaxTextBox1_UnconfirmedPositiveAssertion" 
            onloggingin="OpenIdAjaxTextBox1_LoggingIn" 
            onclientassertionreceived="onauthenticated(sender)" />
        <br />
        <asp:Label ID="Label2" 
            runat="server" AssociatedControlID="TextBox2" EnableViewState="False" 
            Text="お名前:"></asp:Label>
        <br />
        <asp:TextBox ID="TextBox2" runat="server" Width="300px"></asp:TextBox>
        <br />
        <asp:Label ID="Label3" runat="server" AssociatedControlID="TextBox1" 
            EnableViewState="False" Text="コメント:"></asp:Label>
        <br />
        <asp:TextBox ID="TextBox1" runat="server" Height="100px"
            TextMode="MultiLine" Width="300px" EnableViewState="False">
        </asp:TextBox>
        <br />
        <asp:Button ID="Button1" runat="server" Text="送信"
            onclick="Button1_Click" />
        <br />
        <br />
        <asp:Label ID="MessageLabel" runat="server" EnableViewState="False">
        </asp:Label>
    </div>
    </form>
</body>
</html>
}}

#code(csharp){{
<%@ Page Language="C#" %>

<%@ Register assembly="DotNetOpenId" namespace="DotNetOpenId.RelyingParty"
 tagprefix="RP" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

    protected void Button1_Click(object sender, EventArgs e)
    {
        //認証に成功しているか調べる
        if (OpenIdAjaxTextBox1.AuthenticationResponse != null &&
            OpenIdAjaxTextBox1.AuthenticationResponse.Status ==
                AuthenticationStatus.Authenticated)
        {
            //書き込みに成功したことにする(テストなので、そのふりだけ)
            string ci = OpenIdAjaxTextBox1.AuthenticationResponse.ClaimedIdentifier;
            MessageLabel.Text = Server.HtmlEncode(ci) +
                "さんはコメントを書き込みました。";
        }
        else
        {
            MessageLabel.Text = "ログインしてください。";
        }
    }

    protected void OpenIdAjaxTextBox1_LoggingIn(object sender, OpenIdEventArgs e)
    {
        //ニックネームを要求する
        DotNetOpenId.Extensions.SimpleRegistration.ClaimsRequest cr =
            new DotNetOpenId.Extensions.SimpleRegistration.ClaimsRequest();
        cr.PolicyUrl = new Uri(Request.Url, Response.ApplyAppPathModifier(
            "~/PrivacyPolicy.aspx"));
        cr.Nickname = DotNetOpenId.Extensions.SimpleRegistration.DemandLevel.Request;
        e.Request.AddExtension(cr);
    }

    protected void OpenIdAjaxTextBox1_UnconfirmedPositiveAssertion(
        object sender, OpenIdEventArgs e)
    {
        OpenIdAjaxTextBox1.RegisterClientScriptExtension<
            DotNetOpenId.Extensions.SimpleRegistration.ClaimsResponse>("sreg");
    }

</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>OpenIDテスト</title>

<script type="text/javascript">
    function onauthenticated(sender) {
        var name = document.getElementById('<%=TextBox2.ClientID%>');
        if (sender) {
            if (sender.sreg && sender.sreg.nickname) {
                //個人情報(ニックネーム)を表示する
                name.value = sender.sreg.nickname;
            } else {
                //Claimed Identifierを表示する
                name.value = sender.getClaimedIdentifier();
            }
        }
    }
</script>

</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Label ID="Label1" runat="server" AssociatedControlID="OpenIdAjaxTextBox1" 
            EnableViewState="False" Text="OpenID:"></asp:Label>
        <br />
        <RP:OpenIdAjaxTextBox ID="OpenIdAjaxTextBox1" runat="server" 
            onunconfirmedpositiveassertion=
                "OpenIdAjaxTextBox1_UnconfirmedPositiveAssertion" 
            onloggingin="OpenIdAjaxTextBox1_LoggingIn" 
            onclientassertionreceived="onauthenticated(sender)" />
        <br />
        <asp:Label ID="Label2" 
            runat="server" AssociatedControlID="TextBox2" EnableViewState="False" 
            Text="お名前:"></asp:Label>
        <br />
        <asp:TextBox ID="TextBox2" runat="server" Width="300px"></asp:TextBox>
        <br />
        <asp:Label ID="Label3" runat="server" AssociatedControlID="TextBox1" 
            EnableViewState="False" Text="コメント:"></asp:Label>
        <br />
        <asp:TextBox ID="TextBox1" runat="server" Height="100px"
            TextMode="MultiLine" Width="300px" EnableViewState="False">
        </asp:TextBox>
        <br />
        <asp:Button ID="Button1" runat="server" Text="送信"
            onclick="Button1_Click" />
        <br />
        <br />
        <asp:Label ID="MessageLabel" runat="server" EnableViewState="False">
        </asp:Label>
    </div>
    </form>
</body>
</html>
}}

**OpenIdTextBoxコントロール [#z14f2f63]

OpenIdTextBoxコントロールは、OpenIdLoginコントロールのテキストボックスの部分だけのようなコントロールです。OpenIdTextBoxコントロールはOpenIdLoginコントロールの基本クラスですので、多くの機能が共通しています。

OpenIdTextBoxコントロールで認証を開始するには、LogOnメソッドを呼び出します。

OpenIdLoginコントロールとかぶる点が多いため、詳しい説明は省略します。

**OpenIdMobileTextBoxコントロール [#hd3f3770]

OpenIdMobileTextBoxコントロールは、モバイルWebページ用のOpenIdTextBoxコントロールといったようなコントロールです。使い方はほぼOpenIdTextBoxコントロールと同じです。

**次回予告 [#lf52c41a]

次回は、特別なコントロールを使わない方法を紹介する予定です。

**コメント [#e81a7019]

#comment

//これより下は編集しないでください
#pageinfo([[:Category/.NET]] [[:Category/ASP.NET]],2009-07-16 (木) 00:04:41,DOBON!,2016-02-26 (金) 22:15:58,DOBON!)
[ トップ ]   [ 編集 | 差分 | バックアップ | 添付 | 複製 | 名前変更 | リロード ]   [ 新規 | 子ページ作成 | 一覧 | 単語検索 | 最終更新 | ヘルプ ]