SOAPをHTTPにバインディングしている限り不要とも思えるWSE。しかし、WCFにも組み込まれると言われれば無視することもできません(?)。一応Amazon Web Serviceでも少し使っているみたいだし、どんなことができるのか調べてみましょう。
WSE 3.0 のインストール
Web Services Enhancements (WSE) 3.0 for Microsoft .NET からダウンロードしてインストール。尚、インストールする前に一度もVisual Studio 2005 を起動したことがないと、ソリューションエクスプローラのコンテキストメニューに[WSE Setting 3.0]が表示されないみたいです。再インストール時には気をつけねば…
さらに注意:VistaのVisual Studio 2005 のコンテキストメニューに[WSE Setting 3.0]が表示させるにはマニュアルでアドインを追加するしかないみたいです。何度かインストールとアンインストールを繰り返して試してみたのですがダメでした。ユーザのフォルダ構成が変わったからかもしれません。C:\Users\ganfield\Documents\Visual Studio 2005にAddinsフォルダを作成し、その中にWindows XP等から持ってきたアドインファイルをコピったらコンテキストメニューに[WSE Setting 3.0]が表示されました。アドインファイルはC:\Documents and Settings\All Users\Application Data\Microsoft\MSEnvShared\Addinsにあります。(ここ以外の場合もあります。詳しくはVisual Studio 2005 の[オプション]のアドインファイルパスを参照)
WSE 3.0 を使ったWebサービスサーバ
- [新規作成]→[Webサイト]からASP.NET Webサービスを作成します。
- 参照にMicrosoft.Web.Service3を追加します。
- [ソリューションエクスプローラ]から[WSE Setting 3.0]を起動します。
- [General]タブで[Enable this project for Web Services Enhancements]と[Enable Microsoft Web Services Enhancement SOAP Protocol Factory]のチェックボックスをオンにする。
- [Policy]タブで[Enable Policy]チェックボックスをオンにし、[Edit Application Policy]パネルにある[Add]ボタンを押す。Policyの名前を「UsernameServerPolicy」とし、[OK]を押す。
- 新たに出てきたダイログボックスで[Next]を押し、Authentication Settings画面で[Secure a service application]と[username]ラジオボタンをオンにし、[Next]を押す。
- User and Roles画面で、[Perform Authorization]チェックボックスをオンにし、アクセス権を与えるユーザを選び、[Next]を押す。ユーザ名はしっかりと「コンピュータ名\ユーザ名」で記述する必要があります。
- Message Protection画面で[Protection Order]の[None]ラジオボタンをオンにし、[Next]を押します。
- Create Secure Settings画面で設定を確認したら[Finish]を押します。
- Web.configの内容とwse3policyCache.configファイルが自動生成されます。
- WebサービスのクラスにPolicyAttributeを付与します。Policy名は先ほど作成したUsernameServerPolicyを使用します。
[WebService(Namespace = "http://ganfield.website4.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[Policy("UsernameServerPolicy")]
public class Service : System.Web.Services.WebService
サーバ側のコード
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using Microsoft.Web.Services3;
[WebService(Namespace = "http://ganfield.website4.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[Policy("UsernameServerPolicy")]
public class Service : System.Web.Services.WebService
{
public Service () {
}
[WebMethod]
public string HelloWorld(string name) {
return "Hello World " + name + " !!";
}
}
web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="microsoft.web.services3" type="Microsoft.Web.Services3.Configuration.WebServicesConfiguration, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</configSections>
<system.web>
<webServices>
<soapExtensionImporterTypes>
<add type="Microsoft.Web.Services3.Description.WseExtensionImporter, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</soapExtensionImporterTypes>
<soapServerProtocolFactory type="Microsoft.Web.Services3.WseProtocolFactory, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</webServices>
<compilation debug="true">
<assemblies>
<add assembly="Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<!--<add assembly="Microsoft.Web.Services2, Version=2.0.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />-->
</assemblies>
</compilation>
</system.web>
<microsoft.web.services3>
<security>
</security>
<policy fileName="wse3policyCache.config" />
</microsoft.web.services3>
</configuration>
wse3policyCache.config
<policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy">
<extensions>
<extension name="authorization" type="Microsoft.Web.Services3.Design.AuthorizationAssertion, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<extension name="usernameForCertificateSecurity" type="Microsoft.Web.Services3.Design.UsernameForCertificateAssertion, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<extension name="x509" type="Microsoft.Web.Services3.Design.X509TokenProvider, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<extension name="requireActionHeader" type="Microsoft.Web.Services3.Design.RequireActionHeaderAssertion, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<extension name="usernameOverTransportSecurity" type="Microsoft.Web.Services3.Design.UsernameOverTransportAssertion, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</extensions>
<policy name="UsernameServerPolicy">
<authorization>
<allow user="コンピュータ名\ユーザ名" />
<deny user="*" />
</authorization>
<usernameOverTransportSecurity />
<requireActionHeader />
</policy>
</policies>
WSE 3.0 を使ったWebサービスクライアント
- [新規作成]→[プロジェクト]からコンソールアプリを作成します。
- Web参照にWebサービスを追加します。
- 参照にMicrosoft.Web.Service3を追加します。
- [ソリューションエクスプローラ]で[すべてをファイルを表示]をオンにし、[Web Reference]の中からReference.csを探し出し、コードを表示します。
- Reference.csのプロキシクラスのスーパークラスをMicrosoft.Web.Services3.WebServicesClientProtocolに変更します。(プロキシクラスにサービス名 + Wseというクラスがある場合、5.の作業は飛ばして下さい。WSDLツールがWSEに対応したクラスを自動生成しています。)
- [ソリューションエクスプローラ]から[WSE Setting 3.0]を起動します。
- [General]タブで[Enable this project for Web Services Enhancements]チェックボックスをオンにする。
- [Policy]タブで[Enable Policy]チェックボックスをオンにし、[Edit Application Policy]パネルにある[Add]ボタンを押す。Policyの名前を「UsernameClientPolicy」とし、[OK]を押す。
- 新たに出てきたダイログボックスで[Next]を押し、Authentication Settings画面で[Secure a client application]と[username]ラジオボタンをオンにし、[Next]を押す。
- Optionally provide Username and Password画面で、ユーザ名とパスワードを入力し、[Next]を押す。ユーザ名の前にコンピュータ名を記述する必要はありません。
- Message Protection画面で[Protection Order]の[None]ラジオボタンをオンにし、[Next]を押します。
- Create Secure Settings画面で設定を確認したら[Finish]を押します。
- app.configの内容とwse3policyCache.configファイルが自動生成されます。
- プロキシクラスのSetPolicyメソッドを使用してPolicyを設定します。Policy名は先ほど作成したUsernameClientPolicyを使用します。 proxy.SetPolicy("UsernameClientPolicy");
- ビルドして実行する。
クライアント側のコード
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
WebSite4.SampleServiceWse proxy = new WebSite4.SampleServiceWse();
proxy.SetPolicy("UsernameClientPolicy");
Console.WriteLine(proxy.HelloWorld("aaa"));
Console.ReadLine();
}
}
}
app.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="ConsoleApplication2.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
<section name="microsoft.web.services3" type="Microsoft.Web.Services3.Configuration.WebServicesConfiguration, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</configSections>
<applicationSettings>
<ConsoleApplication2.Properties.Settings>
<setting name="ConsoleApplication2_WebReference_Service" serializeAs="String">
<value>http://192.168.xx.yy/testwebroot/website4/SampleService.asmx</value>
</setting>
</ConsoleApplication2.Properties.Settings>
</applicationSettings>
<microsoft.web.services3>
<policy fileName="wse3policyCache.config" />
</microsoft.web.services3>
</configuration>
wse3policyCache.config
<policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy">
<extensions>
<extension name="usernameOverTransportSecurity" type="Microsoft.Web.Services3.Design.UsernameOverTransportAssertion, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<extension name="username" type="Microsoft.Web.Services3.Design.UsernameTokenProvider, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<extension name="requireActionHeader" type="Microsoft.Web.Services3.Design.RequireActionHeaderAssertion, Microsoft.Web.Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</extensions>
<policy name="UsernameClientPolicy">
<usernameOverTransportSecurity>
<clientToken>
<username username="ユーザ名" password="ひ・み・つ" />
</clientToken>
</usernameOverTransportSecurity>
<requireActionHeader />
</policy>
</policies>
SOAP Request
SOAP Response
今回は簡単な認証ということで、UsernameTokenを使用してWebサービスを拡張しましたが、この他にもセキュリティトークンとしてX509SecurityTokenやKerberosToken等があります。また、独自のセキュリティトークンを作成し、使用することもできます。相互運用面に関しては調査しないといけないかもしれませんが、よりセキュアなWebサービスを、と思う方は一度使ってみてはいかがでしょうか?
え?SSL+クライアント証明書で十分?ソンナ、ソンナ…w