WCF サービスで動作するトランスポート セキュリティでユーザー名認証を取得するために、このチュートリアルに従っています。ただし、チュートリアルでは、 basicHttpBinding
which is unacceptable - I requireの使用について言及していますwsHttpBinding
。
BasicAuthenticationModule
アイデアは、HTTP 要求から「Authorization」ヘッダーを読み取り、「Authorization」ヘッダーの内容に従って認証プロセスを実行する WCF サービスのカスタムを持つことです。問題は、「Authorization」ヘッダーが欠落していることです!
IClientMessageInspector
発信メッセージを操作し、カスタム SOAP ヘッダーを追加するために、カスタム動作を実装しました。BeforeSendRequest
関数に次のコードを追加しました。
HttpRequestMessageProperty httpRequest = request.Properties.Where(x => x.Key == "httpRequest").Single().Value;
httpRequest.Headers.Add("CustomHeader", "CustomValue");
これは機能するはずであり、多くの Web リソースによるとbasicHttpBinding
、wsHttpBinding
. 「動作する」とは、WCF サービスがヘッダーを正常に受信したことを意味します。
これは、WCF サービス側で受信した HTTP メッセージを検査する単純化された関数です。
public void OnAuthenticateRequest(object source, EventArgs eventArgs)
{
HttpApplication app = (HttpApplication)source;
//the Authorization header is checked if present
string authHeader = app.Request.Headers["Authorization"];
if (string.IsNullOrEmpty(authHeader))
{
app.Response.StatusCode = 401;
app.Response.End();
}
}
2011 年 9 月付けのこのスレッドの下部の投稿では、これは では不可能であると述べていwsHttpBinding
ます。私はその返事を受け入れたくない。
補足として、IIS に組み込まれている基本認証モジュールを使用し、カスタム モジュールを使用しないと、次のようになります。
The parameter 'username' must not include commas.**
Roles.IsInRole("RoleName")
または `[PrincipalPermission(SecurityAction.Demand, Role = "RoleName")]を試行したときのエラー メッセージ
おそらく、証明書ベースのメッセージ セキュリティでセキュリティをPrimaryIdentity.Name
使用しているため、プロパティに証明書のサブジェクト名が含まれているためです。TransportWithMessageCredential
問題に対する代替アプローチだけでなく、提案も受け付けています。ありがとう。
アップデート
お分かりのように、HTTP ヘッダーは、後で WCF サービス コード全体で正しく読み取られます。
(HttpRequestMessageProperty)OperationContext.Current.IncomingMessageProperties["httpRequest"]
カスタムヘッダーが含まれています。ただし、これは既にメッセージ レベルです。トランスポート認証ルーチンにヘッダーを渡す方法は?
更新 2
少し調査した結果、Web ブラウザーが HTTP ステータス コード 401 を受信すると、資格情報を指定できるログイン ダイアログが表示されるという結論に達しました。ただし、WCF クライアントは単に例外をスローし、資格情報を送信したくありません。https://myserver/myservice/service.svc
Internet Explorer でアクセスしたときに、この動作を確認できましたこのリンクからの情報を使用して修正しようとしましこれは WCF のバグですか、それとも何か不足していますか?
編集
これが私のsystem.servicemodel
(からのweb.config
)関連セクションです - 私はそれを正しく設定したと確信しています。
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="ChainTrust" revocationMode="NoCheck" />
</clientCertificate>
<serviceCertificate findValue="server.uprava.djurkovic-co.me" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My" />
</serviceCredentials>
<serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="AspNetSqlRoleProvider" />
</behavior>
</serviceBehaviors>
................
<wsHttpBinding>
<binding name="EndPointWSHTTP" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="20480000" maxReceivedMessageSize="20480000" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
<readerQuotas maxDepth="20480000" maxStringContentLength="20480000" maxArrayLength="20480000" maxBytesPerRead="20480000" maxNameTableCharCount="20480000" />
<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Basic" />
<message clientCredentialType="Certificate" negotiateServiceCredential="true" algorithmSuite="Default" />
</security>
</binding>
</wsHttpBinding>
............
<service behaviorConfiguration="ServiceBehavior" name="DjurkovicService.Djurkovic">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="EndPointWSHTTP" name="EndPointWSHTTP" contract="DjurkovicService.IDjurkovic" />
</service>
サービスによって返される例外は次のとおりです。
HTTP 要求は、クライアント認証スキーム「匿名」では許可されていません。サーバーから受信した認証ヘッダーは「Basic Realm,Negotiate,NTLM」でした。(リモート サーバーがエラーを返しました: (401) Unauthorized.)