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 值,但没有一个起作用。我还自托管了 WCF 服务,以消除与 IIS 在服务获得机会之前尝试对用户进行身份验证相关的问题。

任何关于潜在问题的评论将不胜感激。谢谢。

更新:感谢 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

首先,您可能希望将 WCF 跟踪添加到您的服务以获取更多详细信息。其次,我认为问题可能是您以明文形式发送用户凭据,而 WCF 不允许通过不安全的传输通道以明文形式传输用户凭据。因此,请尝试使用 https 或指定加密算法以通过 http 保护用户凭据。

于 2009-04-28T00:14:21.477 回答
0

上面的 atconway建议似乎是正确的方法,但您的服务必须从标头读取 base 64 字符串数据并转换回字符串,然后进行身份验证。但它需要在每次调用时进行身份验证。

另一种方法是使用安全密钥。和令牌

  1. 每个客户端都有他在第一次请求时发送的安全密钥,可能在标头中。
  2. 您可以生成密钥,例如 key = MD5Hash(username+password);
  3. 作为响应,他获得了令牌,然后在每个请求中发送令牌。令牌可以是 Guid。每个令牌在x分钟后过期。
  4. 在服务器端,您可以维护一个像 Dictionay 这样的单例字典,以在当前时间 > 过期时间将其从字典中删除时检查令牌过期。
  5. 要更新会话,请将更新会话方法放入您的代码中。

为了极高的安全性

拥有私钥/公钥对,客户端将使用公钥加密整个帖子数据,您将使用私钥解密。

于 2013-02-02T06:31:50.050 回答