2

この質問の続きとして、dotnetopenauthに問題があります。

証明書利用者コードに移動してリクエストを作成しましたが、プロバイダーがリクエストを受信するとOpenIdProvider.GetRequest()nullを返します。私はコードを調べましたが、私が知る限り、これはopenidペイロード(request.form)が依存側によって配信されていないためです。しかし、これがなぜなのか理解できません。

コード:

依拠当事者:

public ActionResult Authenticate(string RuserName = "")
{
UriBuilder returnToBuilder = new UriBuilder(Request.Url);
returnToBuilder.Path = "/OpenId/Authenticate";
returnToBuilder.Query = null;
returnToBuilder.Fragment = null;

Uri returnTo = returnToBuilder.Uri;
returnToBuilder.Path = "/";
Realm realm = returnToBuilder.Uri;

var response = openid.GetResponse();

if (response == null) {
    if (Request.QueryString["ReturnUrl"] != null && User.Identity.IsAuthenticated) {

    } else {

    string strIdentifier = "http://localhost:3314/User/Identity/" + RuserName;
    var request = openid.CreateRequest(
        strIdentifier,
        realm,
        returnTo);

    var fetchRequest = new FetchRequest();
    request.AddExtension(fetchRequest);
    request.RedirectToProvider();
    }
} else {
    switch (response.Status) {
        case AuthenticationStatus.Canceled:
            break;
        case AuthenticationStatus.Failed:
            break;
        case AuthenticationStatus.Authenticated:
            //log the user in
            break;
    }
}

return new EmptyResult();

}

プロバイダー:

public ActionResult Index()
{
    IRequest request = OpenIdProvider.GetRequest();

    if (request != null) {
        if (request.IsResponseReady) {
            return OpenIdProvider.PrepareResponse(request).AsActionResult();
        }

        ProviderEndpoint.PendingRequest = (IHostProcessedRequest)request;
        return this.ProcessAuthRequest();
    } else {
        //user stumbled on openid endpoint - 404 maybe?
        return new EmptyResult();
    }
 }

public ActionResult ProcessAuthRequest()
    {
        if (ProviderEndpoint.PendingRequest == null) {
            //there is no pending request
            return new EmptyResult();
        }

        ActionResult response;
        if (this.AutoRespondIfPossible(out response)) {
            return response;
        }

        if (ProviderEndpoint.PendingRequest.Immediate) {
            return this.SendAssertion();
        }

        return new EmptyResult();
    }

ログ:

RP:1)http://pastebin.com/Pnih3ND7 2)http://pastebin.com/eBzGun9y

プロバイダー: http: //pastebin.com/YAUTBzHk

興味深いことに、RPログにはローカルホストが信頼されていないことが示されています...それでも、web.configのホワイトリストに登録されたホストに追加したところ、昨日は「機能」していました...

編集:さて、これは奇妙です。昨日、私は問題が何であるかを見つけようとしてDNOAソースをステップスルーしていました。log4netを有効にすると、ログファイルが作成され、空白のままになりました。今日、log4netを再度セットアップしました。ログは正常に記録されましたが、意味をなさないエラーが発生しました(上記を参照)。また、DNOAソースに足を踏み入れることができませんでした。dotnetopenauth.dllへの参照を削除して再度追加すると、ホワイトリストに登録されたホストでの「元のエラー」が消え、ソースにステップインできましたが、ログファイルが再び空白になりました。そして、request.formが入力されないという問題があります...

EDIT2:両方のコントローラーの名前は「OpenIdController」(RPとEPの両方)です。私のRPはlocalhost:1903で実行されており、エンドポイントはlocalhost:3314で実行されています。


EDIT3:私が変更を加えた後、あなたは物事が機能し始めたことを提案しました。RPは検出を正常に実行しますが、実際に要求を行うときに問題が発生します。

この行IRequest i_request = OpenIdProvider.GetRequest();は正常に機能しますが、キャストしようとするとIAuthenticationRequest iR = (IAuthenticationRequest)i_request;、次のエラーが発生します。

 System.InvalidCastException was unhandled by user code
 Message=Unable to cast object of type     'DotNetOpenAuth.OpenId.Provider.AutoResponsiveRequest' to type 'DotNetOpenAuth.OpenId.Provider.IAuthenticationRequest'.
 Source=Portal
 StackTrace:
   at Portal.Controllers.OpenIdController.Index() in Controllers\OpendIdController.cs:line 35
   at lambda_method(Closure , ControllerBase , Object[] )
   at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
   at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass42.<BeginInvokeSynchronousActionMethod>b__41()
   at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _)
   at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.End()
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult)
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass37.<>c__DisplayClass39.<BeginInvokeActionMethodWithFilters>b__33()
   at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49()

このコードは、私が関連性があると思った2つのサンプルの間のちょっとした寄せ集めです。SSOタイプの環境を設定したいので、使用しているコードの大部分は\DotNetOpenAuth-4.1.0.12182\Samples\OpenIdWebRingSsoProvider\Code\Util.cs(ProcessAuthenticationChallenge関数)からのものです。ただし、その関数はIAuthenticationRequestOpenIdProvider.GetRequestが返すことを期待しているため、クラスAutoResponsiveRequestのプロパティとメソッドを使用するためにキャストできると考えました。IAuthenticationRequest明らかに私は間違っていました。

現時点では、どうやってアプローチするのかよくわかりません。OpenIdProviderMVCサンプルのサンプルコードを使用する必要がありますか?重要なのは、ログインがシングルサインオンのように機能し、ユーザーが実際にOpenIdの入力を求められることはないということです。エンドポイントも1つだけです(ただし、複数のRPがあります)。

最新のRPログへのリンクは次のとおりです:http://pastebin.com/enpwYqq3


EDIT4:私はあなたが提案したことをし、そしていくらかの進歩を遂げました。私のEPは応答を受け取り、私が知る限りそれを処理しますが、レルムURLにリダイレクトすると、エラーが発生します。

012-10-10 13:55:01,171 (GMT-4) [25] ERROR DotNetOpenAuth.Messaging - Protocol error: An HTTP request to the realm URL (http://localhost:1903/) resulted in a redirect, which is not allowed during relying party discovery.

Realmとは対照的に、の機能は正確には何ReturnToですか?サンプルコードを使用すると、Realmが最終的にhttp://localhost:1903/なり、ReturnToが最終的には問題ないhttp://localhost:1903/OpenId/Authenticateように見えます。EPがレルムにリクエストを送信する必要があるのはなぜですか?処理が終了したら、returnToにアサーションを送信するだけでよいと思っていました。レルムを手動で設定するとhttp://localhost:1903/OpenId/AuthenticaterelyingParty.GetResponse()nullが返されます。

誰かがベースURL(http://localhost:1903)にアクセスしたときにリダイレクトするようにアプリケーションを設定しています-DNOA EPリクエストをインターセプトするためにそこで実行する必要があるコードは何ですか?

新しいログ:

RP: http: //pastebin.com/L9K5Yft4

EP: http: //pastebin.com/kBPWiUxp

また、質問の冒頭のコードを更新して、行った変更をより適切に反映させました。


EDIT5:レルムはアプリケーションの実際のベースURLである必要がありますか?つまり、(http://localhost:1903)?既存のアーキテクチャを使用すると、リダイレクトを削除するのは困難です。レルムをベースのOpenIdコントローラー(http://localhost:1903/OpenId)に設定してみましたが、手動でテストするとXRDSドキュメントが生成されました。ただし、アプリケーションがフリーズしているようで、EPログに次のエラーが表示されます。

2012-10-10 15:17:46,000 (GMT-4) [24] ERROR DotNetOpenAuth.OpenId - Attribute Exchange extension did not provide any aliases in the if_available or required lists.

4

2 に答える 2

2

あなたのRPには非常に疑わしい奇妙なコードがあります。return_toとレルムの両方が同じURI権限を持つのは通常のことですが(実際には必須です)、最初のパラメーターとして渡すユーザー指定の識別子はOpenIdRelyingParty.CreateRequest、依存しているものと同じホストとポートを持っているという事実パーティーはとても奇妙です。通常、渡す識別子はプロバイダーによってホストされているURLになります。さて、ポート3314があなたのRPなのかOPなのかはわかりませんが、どちらにしても、RPコードのこれらのポート番号の1つが間違っているように見えます。

次に、ユーザーIDの検出は、null参照例外で失敗します(RPログのv2による)。これにより、ログイン要求がプロバイダーに到達するのを防ぐことができます。プロバイダー呼び出されているが、OpenIDリクエストが存在しないという事実は、それhttp://localhost:3314/OpenId/が実際にはOPエンドポイント(OpenIDリクエストを読み取るOpenIDプロバイダーのアクションメソッドのURL)であることを示しています。それは不適切でしょう。メソッドの最初のパラメーターに渡す必要OpenIdRelyingParty.CreateRequestのあるURLも、OPエンドポイントではなくユーザーのOpenIDURLである必要があります。ユーザーのOpenIDURLを設定する方法の例については、OpenIdProviderMvcサンプルのユーザーコントローラーを確認してください。次に、そのURLを最初の引数として使用しますCreateRequest

第3に、プロバイダーがnull以外の要求を受信すると、常にそれをにキャストできるとは限りませんIAuthenticationRequest。すべてのOpenIDメッセージが認証メッセージであるとは限りません。一部は、基盤となるOpenIDプロトコルの一部です。OpenIdProviderMvcサンプルのOpenIDコントローラーを見ると、さまざまなメッセージタイプを処理するための条件付きキャストがあることに注意してください。コントローラで同様のメッセージ処理を行う必要があります。

SSOシナリオを使用するため、コントローラーの大きな違いはおそらく次のようになります。

  1. コントローラはログインページへのリダイレクトで応答することはありませんが、ユーザーが誰であるかを「魔法のように」把握します。
  2. IAuthenticationRequest.Realmコントローラは、SSO Webリングに含まれているRPのホワイトリストに対してプロパティをチェックし、レルムが適格である場合にのみポジティブアサーションを提供する必要があります。これにより、サーバーがセットアップされると、OpenIDプロバイダーを静かに使用して、ランダムなインターネットWebサイトのユーザーが組織に属している場合にそのユーザーを識別し、プライバシーを侵害するサイトを誰でもセットアップできるという攻撃が軽減されます。

第4に、OPがRPの「レルム」URLに送信するHTTPリクエストは、OpenIDが「RP検出」を呼び出すプロセスの一部です。「オープンリダイレクタ」攻撃を軽減するためにあります。リダイレクトしないようにRPのベースURLを調整する必要がありますが、RP検出要求が受信されたときにXRDSドキュメントを返す必要があります。通常のブラウザの場合でもリダイレクトできます。これを行う方法の例は、OpenIdRelyingPartyMvcサンプルのHomeControllerで確認できます。

于 2012-10-06T14:22:02.400 に答える
1

証明書利用者のログからわかるように、次のようになります。

ERROR DotNetOpenAuth.Messaging - Protocol error: The URL 'http://localhost:3314/OpenId/' is rated unsafe and cannot be requested this way.

プロバイダーはローカルホストでホストされていますが、本番サーバーでは安全なOpenIDではありません。したがって、デフォルトではlocalhostは無効になっています。configSectionsこれをweb.configファイル(上部に適切なものを含む)に追加することにより、ローカルホストをホワイトリストに追加することで、ローカルテストを許可できます。

<dotNetOpenAuth>
    <messaging>
        <untrustedWebRequest>
            <whitelistHosts>
                <add name="localhost" />
            </whitelistHosts>
        </untrustedWebRequest>
    </messaging>
</dotNetOpenAuth>
于 2012-09-28T00:20:11.207 に答える