2004年11月10日

Web サービス呼び出しの認証

Web サービスを呼び出すアプリケーションを開発していると、「HTTP ステータス: 401 Access Denied で要求が失敗しました。」というエラーが発生することがあると思います。
このエラーは、HTTP ステータスと書かれている通り、Web サービスやSOAPのエラーではなく、Web サーバーの認証エラーになります。

ここで、どのような対処をするかは認証方式によって変わってきます。
Kerberos 認証 NTLM 認証などの統合 Windows 認証の場合で、クライアントが認証済みの場合、
クライアント アプリケーションはすでに資格情報を持っています。
そのため、以下のようにSystem.Net.CredentialCache.DefaultCredentialsを渡すだけでOKです。
using(WS.Service1 service = new WebServiceWinClient.WS.Service1())
{
service.Credentials = System.Net.CredentialCache.DefaultCredentials;
MessageBox.Show(service.HelloWorld());
}

基本認証の場合は、Credentialを作成してやる必要があります。

using(WS2.Service2 service = new WebServiceWinClient.WS2.Service2())
{
service.Credentials = new System.Net.NetworkCredential("test", "test");
MessageBox.Show(service.HelloWorld());
}

ここでは、ユーザーID:test、パスワード:testというアカウントを使用しています。

ではこの時、どのようなリクエストが送られるか見てみましょう。
まず、最初のリクエストは認証方法にかかわらず以下のような情報が送られます。
SOAPのメッセージも送られています。
POST /WebService1/Service1.asmx HTTP/1.1
User-Agent:
Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 1.1...)
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://tempuri.org/HelloWorld"
Content-Length: 288
Expect: 100-continue
Connection: Keep-Alive
Host: localhost:80

<?xml version="1.0" encoding="utf-8"?>
<
soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<
soap:Body><HelloWorld xmlns="http://tempuri.org/" /></soap:Body>
</
soap:Envelope>

そして、IISからは次のようなレスポンスが返ってきます。
HTTP/1.1 401 Access Denied
Server: Microsoft-IIS/5.1
Date: Wed, 10 Nov 2004 02:39:02 GMT
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
Proxy-Connection: close
Connection: close
Content-Length: 4395
Content-Type: text/html

WWW-AuthenticateにNTLMが返ってきているのがわかります。
これでNTLM認証が必要だとわかります。

基本認証の時は、以下のレスポンスがあります。
HTTP/1.1 401 Access Denied
Server: Microsoft-IIS/5.1
Date: Wed, 10 Nov 2004 04:17:20 GMT
WWW-Authenticate: Basic realm="localhost"
Proxy-Connection: close
Connection: close
Content-Length: 4395
Content-Type: text/html

WWW-AuthenticateにBasicが返ってきているのがわかります。

2回目のリクエストで、NTLMの場合は、以下のようにAuthorization:というヘッダを渡しています。
以下のように暗号のような文字列が渡されています。
POST /WebService1/Service1.asmx HTTP/1.1
User-Agent:
Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 1.1...)
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://tempuri.org/HelloWorld"
Authorization: Negotiate TlRMTVNTUAABAAAAt7AMACgQU8wM0FOVC5DTy5KUA==
Content-Length: 288
Expect: 100-continue
Host: localhost:80

<?xml version="1.0" encoding="utf-8"?>
<
soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<
soap:Body><HelloWorld xmlns="http://tempuri.org/" /></soap:Body>
</
soap:Envelope>



基本認証の方は、Authorization:というヘッダを渡しています。

POST /WebService1/Service1.asmx HTTP/1.1
User-Agent:
Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 1.1...)
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://tempuri.org/HelloWorld"
Authorization: Basic dGVzdDp0ZXN0
Content-Length: 288
Expect: 100-continue
Host: localhost:80

<?xml version="1.0" encoding="utf-8"?>
<
soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<
soap:Body><HelloWorld xmlns="http://tempuri.org/" /></soap:Body>
</
soap:Envelope>

こちらも、「dGVzdDp0ZXN0」という暗号のような文字列が渡されています。
ところが、こちらは単純なBASE 64のエンコードで、デコードしてやると「test:test」という単純な文字列が取得できます。


統合 Windows 認証はもう一回同じようなやりとりがあるのですが、割愛させて頂きます。

このように、認証情報をやりとりすることで認証が必要なWeb サービスを呼び出すことができます。
ここでは、ACLによるセキュリティを説明しましたが、SOAPヘッダに認証情報を含める認証方法もあります。


この記事へのトラックバックURL

http://trackback.blogsys.jp/livedoor/omssys/9119880
この記事へのコメント
情報提供ありがとうございます。ちょうど不具合連絡を受けた内容でしたので、助かりました。
Posted by tensai at 2004年11月26日 18:01
コメントありがとうございます。

今後も欲しい情報やご要望等ありましたらどこかに書き込んでください。
Posted by om at 2004年11月26日 23:39