8

WCT REST サービスを公開しようとしていますが、有効なユーザー名とパスワードを持つユーザーのみがアクセスできます。ユーザー名とパスワードは SQL データベースに保存されます。

サービス契約は次のとおりです。

public interface IDataService
{
    [OperationContract]
    [WebGet(ResponseFormat = WebMessageFormat.Json)]
    byte[] GetData(double startTime, double endTime);
}

WCF 構成は次のとおりです。

<bindings>
  <webHttpBinding>
    <binding name="SecureBinding">
      <security mode="Transport">
        <transport clientCredentialType="Basic"/>
      </security>
    </binding>
  </webHttpBinding>
</bindings>
<behaviors>
  <serviceBehaviors>
    <behavior name="DataServiceBehavior">
      <serviceMetadata httpGetEnabled="true"/>
      <serviceCredentials>
        <userNameAuthentication
           userNamePasswordValidationMode="Custom"
           customUserNamePasswordValidatorType=
                 "CustomValidator, WCFHost" />
      </serviceCredentials>
    </behavior>
  </serviceBehaviors>
</behaviors>
<services>
  <service behaviorConfiguration="DataServiceBehavior" name="DataService">
    <endpoint address="" binding="webHttpBinding"
              bindingConfiguration="SecureBinding" contract="IDataService" />
  </service>
</services>

Silverlight アプリケーション内の WebClient クラスを介してサービスにアクセスしています。ただし、ユーザー資格情報をサービスに渡す方法を理解できませんでした。client.Credentials のさまざまな値を試しましたが、カスタム バリデーターでコードをトリガーするものはないようです。次のエラーが表示されます: 基になる接続が閉じられました: 送信時に予期しないエラーが発生しました。

ここに私が試したいくつかのサンプルコードがあります:

   WebClient client = new WebClient();
   client.Credentials = new NetworkCredential("name", "password", "domain");
   client.OpenReadCompleted += new OpenReadCompletedEventHandler(GetData);
   client.OpenReadAsync(new Uri(uriString));

セキュリティ モードを [なし] に設定すると、すべてが機能します。他の clientCredentialType 値も試しましたが、どれも機能しませんでした。また、サービスがチャンスを得る前に IIS がユーザーを認証しようとすることに関連する問題を排除するために、WCF サービスを自己ホストしました。

根本的な問題が何であるかについてのコメントは大歓迎です。ありがとう。

更新: Mehmet の優れた提案に感謝します。これが私が持っていたトレース構成です:

 <system.diagnostics>
    <sources>
      <source name="System.ServiceModel"
              switchValue="Information, ActivityTracing"
              propagateActivity="true">
        <listeners>
          <add name="xml" />
        </listeners>
      </source>
      <source name="System.IdentityModel" switchValue="Information, 
               ActivityTracing" propagateActivity="true">
        <listeners>
          <add name="xml" />
        </listeners>
      </source>
    </sources>
    <sharedListeners>
      <add name="xml"
           type="System.Diagnostics.XmlWriterTraceListener"
           initializeData="c:\Traces.svclog" />
    </sharedListeners>
  </system.diagnostics>

しかし、Silverlight クライアントからのメッセージは表示されませんでした。https と http については、次のように https を使用しました。

string baseAddress = "https://localhost:6600/";
_webServiceHost = new WebServiceHost(typeof(DataServices), 
                new Uri(baseAddress));
_webServiceHost.Open();

ただし、SSL 証明書は構成しませんでした。これが問題ですか?

4

3 に答える 3

2

「基本」認証を使用しているため、リクエストヘッダーでユーザー名とパスワードを送信する必要があります。クレデンシャルをヘッダーに手動で追加する例を以下に示します。

HttpWebRequest req = (HttpWebRequest)WebRequest.Create(@"https://localhost:6600/MyWCFService/GetData");
//Add a header to the request that contains the credentials
//DO NOT HARDCODE IN PRODUCTION!! Pull credentials real-time from database or other store.
string svcCredentials = Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes("userName" + ":" + "password"));
req.Headers.Add("Authorization", "Basic " + svcCredentials);
//Parse the response and do something with it...
using (WebResponse svcResponse = (HttpWebResponse)req.GetResponse())
{
  using (StreamReader sr = new StreamReader(svcResponse.GetResponseStream()))
  {
    //Sample parses json response; your code here may be different
    JavaScriptSerializer js = new JavaScriptSerializer();
    string jsonTxt = sr.ReadToEnd();
  }
}
于 2012-07-03T03:07:55.237 に答える
0

上で提案された atconwayは正しい方法のように見えますが、サービスはヘッダーから base 64 文字列データを読み取り、文字列に変換してから認証する必要があります。ただし、すべての呼び出しで認証する必要があります。

もう 1 つの方法は、セキュア キーを使用することです。とトークン

  1. すべてのクライアントは、最初のリクエストで、おそらくヘッダーで送信する安全なキーを持っています。
  2. key = MD5Hash(username+password); のようなキーを生成できます。
  3. 応答として、彼はトークンを取得し、トークンは各リクエストで送信されます。トークンは Guid にすることができます。すべてのトークンはx分後に期限切れになります。
  4. サーバー側では、 Dictionay のようなシングルトン ディクショナリを維持して、現在の時刻 > 有効期限が辞書から削除されたときにトークンの有効期限を確認できます。
  5. セッションを更新するには、renew session メソッドをコードに入れます。

極限のセキュリティのために

秘密鍵と公開鍵のペアがあれば、クライアントは公開鍵を使用して投稿データ全体を暗号化し、秘密鍵を使用して復号化します。

于 2013-02-02T06:31:50.050 に答える