[C#.NET][WCF] wsHttpBinding @self-host 的安全性 使用 Windows UserName 驗証

  • 3479
  • 0
  • WCF
  • 2019-06-24

[C#.NET][WCF] wsHttpBinding @self-host 的安全性 使用 Windows UserName 驗証

上篇 [WCF] 在雲端虛機上部署我的 wsHttpBinding Host,我們學會了如何部署,這次我們來演練設定它的安全性

若你的防火牆還沒設定,請先把防火牆打開,設定規則Port 168,Windows Azure上的 VM 也先設好 EndPoint

 

為了測試,在 Server 端我們需要一個X509的憑證

在Visual Studio Command Prompt (2010)輸入:

makecert -pe -n CN=WCFRoot -ss Root -sr LocalMachine -a sha1 -sky signature
makecert.exe -sr LocalMachine -ss My -a sha1 -n CN=WCFServer -sky exchange -pe -is Root -ir LocalMachine -in WCFRoot

image

 

在MMC控制台就可以看到我們創建的憑證。

image

image


接下來我們就來演練如何設定安全性

Step1.設定 WcfServiceLibrary 專案的 App.Config

image

 

新增一個 wsHttpBinding,並命名為 wsHttpBinding.Config

image

 

使用帳號密碼方式登入

image

 

將這個Service Behavior命名為WcfServiceLibrary.ServiceBehavior,然後新增一個serviceCredentials

image

輸入憑證資訊,CN=WCFServer是憑證名稱

image

 

為第一個 EndPoint 套用 wsHttpBinding 設定

image

 

套用WcfServiceLibrary.ServiceBehavior 設定完成就存檔。

image

 

設定好的 App.Config 如下:


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
 
  <system.web>
    <compilation debug="true" />
  </system.web>
  <!-- When deploying the service library project, the content of the config file must be added to the host's
  app.config file. System.Configuration does not support config files for libraries. -->
  <system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="wsHttpBinding.Config">
          <security>
            <message clientCredentialType="UserName" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <services>
      <service behaviorConfiguration="WcfServiceLibrary.ServiceBehavior"
        name="WcfServiceLibrary.Service">
        <endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttpBinding.Config"
          contract="WcfServiceLibrary.IService">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" bindingConfiguration=""
          contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:168" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="WcfServiceLibrary.ServiceBehavior">
          <serviceCredentials>
            <serviceCertificate findValue="CN=WCFServer" />
            <userNameAuthentication userNamePasswordValidationMode="Windows" />
          </serviceCredentials>
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
 
</configuration>


 
 
按F5測試,順利的掛起WCF Server。
這時候我們會發現,WCF Test Client 的呼叫測試失敗了,原因就是 Client 憑證設定的問題
image

 
Step2.修改Client的App.Conifg
準備好Client的專案後,加入Server的位置當參考
SNAGHTML161d06c7

 
準備修改App.Config
SNAGHTML161e0698

 

改成 WCFServer

SNAGHTML161eed7d

 

新增一個 endpointBehaviors,並命名為 EndPointBehavior.Config,然後再新增一個 clientCredentials

SNAGHTML1620c8ed

 

在authentication節點裡設定以下:
certificateValidationMode="None"
revocationMode="NoCheck"

SNAGHTML16217542

 

套用

SNAGHTML1621f8d3

 

存檔後就可以看到,設定完成的 App.Config


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="EndPointBehavior.Config">
          <clientCredentials>
            <serviceCertificate>
              <authentication certificateValidationMode="None" revocationMode="NoCheck" />
            </serviceCertificate>
          </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <bindings>
      <wsHttpBinding>
        <binding name="WSHttpBinding_IService">
          <security>
            <message clientCredentialType="UserName" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:168/" behaviorConfiguration="EndPointBehavior.Config"
          binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService"
          contract="WcfServiceLibrary.IService" name="WSHttpBinding_IService">
        <identity>
          <dns value="WCFServer" />
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>
</configuration>


 
 
修改EndPoint為遠端位置
SNAGHTML16251336

 

Step3.加入認証方式

Client專案的UI設計如下

SNAGHTML16265a05

 

並加入以下片斷程式碼


private ServiceClient _client = new ServiceClient();

private void button_Login_Click(object sender, EventArgs e)
{
    this.button_GetResult.Enabled = false;
    _client = new ServiceClient();
    this._client.ClientCredentials.UserName.UserName = textBox_UserName.Text;
    this._client.ClientCredentials.UserName.Password = textBox_Password.Text;
    this.button_GetResult.Enabled = true;
}

private void button_GetResult_Click(object sender, EventArgs e)
{
    string result = "";
    try
    {
        result = this._client.SayHello(textBox_UserName.Text);
        MessageBox.Show(result);
    }
    catch (TimeoutException exception)
    {
        var msg = string.Format(exception.Message);
        this._client.Abort();
        MessageBox.Show(msg);
    }
    catch (CommunicationException exception)
    {
        var msg = string.Format(exception.Message);
        this._client.Abort();
        MessageBox.Show(msg);
    }
}

輸入Server端的帳號密碼,驗証登入後,方能取得Server提供的方法。
SNAGHTML1628a383

 


補充:

還有一個設定方式仍可用 Windows User Name 登入,

Step1.設定WcfServiceLibrary專案的App.Config

只有一個設定跟上述不同

image

 

存檔後的 App.Config 如下


<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <system.web>
    <compilation debug="true" />
  </system.web>
  <!-- When deploying the service library project, the content of the config file must be added to the host's
  app.config file. System.Configuration does not support config files for libraries. -->
  <system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="wsHttpBinding.Config">
          <security>
            <message clientCredentialType="Windows" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <services>
      <service behaviorConfiguration="WcfServiceLibrary.ServiceBehavior"
        name="WcfServiceLibrary.Service">
        <endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttpBinding.Config"
          contract="WcfServiceLibrary.IService">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" bindingConfiguration=""
          contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:168" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="WcfServiceLibrary.ServiceBehavior">
          <serviceCredentials>
            <clientCertificate>
              <authentication certificateValidationMode="None" />
            </clientCertificate>
            <serviceCertificate findValue="CN=WCFServer" />
            <userNameAuthentication userNamePasswordValidationMode="Windows"
              customUserNamePasswordValidatorType="" />
          </serviceCredentials>
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

</configuration>

Step2.修改Client端的程式碼

修改如下:


private void button_Login_Click(object sender, EventArgs e)
{
    this.button_GetResult.Enabled = false;
    _client = new ServiceClient();

    this._client.ClientCredentials.Windows.ClientCredential.UserName = this.textBox_UserName.Text;
    this._client.ClientCredentials.Windows.ClientCredential.Password = this.textBox_Password.Text;
    this.button_GetResult.Enabled = true;
}

 

使用Windows驗証方式還能設定Domain,表示這可以用來驗証AD裡的帳號,真帥。


 

image

 

測試結果如下

SNAGHTML1b6203c7

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo