매우 간단한 WCF 앱을 만들었는데 해결할 수없는 문제가 하나 있습니다. 익명 인증이 활성화 된 경우 실제로 작동하는 WCF 서비스와 관련하여 IIS에서이 기능을 비활성화하면 오류가 발생합니다. HTTP 요청이 클라이언트 인증 체계 '익명'으로 인증되지 않았습니다. 서버에서받은 인증 헤더는 ''입니다.
이것은 web.config 구성입니다.
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<services>
<service name="WCFTestApplication.WCFTestApplication">
<endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="WCFTestAppBinding"
contract="WCFTestApplication.IWCFTestApplication"
/>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding messageEncoding="Text" name="WCFTestAppBinding">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="Windows"/>
<transport clientCredentialType="Windows" proxyCredentialType="Windows"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<!--protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping-->
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="false"/>
</system.webServer>
이것은 클라이언트 애플리케이션 소스입니다.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using System.Net;
namespace WCFClientApplication
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private string _name = "";
private string _passwd = "";
private string _domain = "";
public string UserName
{
get { return _name; }
set { _name = value; }
}
public string Password
{
get { return _passwd; }
set { _passwd = value; }
}
public string Domain
{
get { return _domain; }
set { _domain = value; }
}
private void button1_Click(object sender, EventArgs e)
{
//if (!String.IsNullOrEmpty(usrTxt.Text) || !String.IsNullOrEmpty(passTxt.Text) || !String.IsNullOrEmpty(domainTxt.Text))
//{
UserName = usrTxt.Text;
Password = passTxt.Text;
Domain = domainTxt.Text;
WCFClientProxy.WCFTestApplicationClient client = new WCFClientProxy.WCFTestApplicationClient();
client.ClientCredentials.Windows.ClientCredential = new System.Net.NetworkCredential(UserName, Password, Domain);
//System.Net.ServicePointManager.ServerCertificateValidationCallback += (se, cert, chain, sslerror) => { return true; };
textBox1.Text = client.GetData();
//}
//else
//{
// MessageBox.Show("Fields like username, password and domain must not be blank...!","Warning...!",MessageBoxButtons.OK, MessageBoxIcon.Warning);
//}
}
private void domainTxt_MouseHover(object sender, EventArgs e)
{
tipLbl.Visible = true;
}
private void domainTxt_MouseLeave(object sender, EventArgs e)
{
tipLbl.Visible = false;
}
}
}
wcf 인터페이스 :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace WCFTestApplication
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
[ServiceContract]
public interface IWCFTestApplication
{
[OperationContract]
string GetData();
// TODO: Add your service operations here
}
}
수업:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace WCFTestApplication
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
// NOTE: In order to launch WCF Test Client for testing this service, please select Service1.svc or Service1.svc.cs at the Solution Explorer and start debugging.
public class WCFTestApplication : IWCFTestApplication
{
public string GetData()
{
return "WCF is working, and message is authenticated and encrypted";
}
}
}
익명 인증에 MEX 끝점 및 통신에 무언가가 있다는 것을 읽었지만 Windows 로그인을 유지하고 익명 사용자 로그인을 비활성화하여 적절한 자격 증명없이 WCF를 사용할 수 없도록하는 방법은 무엇입니까?
마침내 해결책을 찾았습니다.
Web.config
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<authentication mode="Windows" />
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<services>
<service name="WCFTestApplication.WCFTestApplication">
<endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="WCFTestAppBinding"
contract="WCFTestApplication.IWCFTestApplication"
/>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding messageEncoding="Text" name="WCFTestAppBinding">
<security mode="Transport">
<transport clientCredentialType="Ntlm"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceCredentials>
<windowsAuthentication allowAnonymousLogons="false" includeWindowsGroups="true"/>
</serviceCredentials>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<!--protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping-->
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="false"/>
</system.webServer>
</configuration>
app.config
<?xml version="1.0"?>
<configuration>
<configSections>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
</startup>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IWCFTestApplication">
<security mode="Transport">
<transport clientCredentialType="Ntlm" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://vladimir.intra.jv.hr/WCFTestApplication.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IWCFTestApplication"
contract="WCFTestApplication.IWCFTestApplication" name="WSHttpBinding_IWCFTestApplication">
<identity>
<servicePrincipalName value="host/vladimir.intra.jv.hr" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using System.Net;
namespace WCFClientApplication
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private string _name = "";
private string _passwd = "";
private string _domain = "";
public string UserName
{
get { return _name; }
set { _name = value; }
}
public string Password
{
get { return _passwd; }
set { _passwd = value; }
}
public string Domain
{
get { return _domain; }
set { _domain = value; }
}
private void button1_Click(object sender, EventArgs e)
{
//if (!String.IsNullOrEmpty(usrTxt.Text) || !String.IsNullOrEmpty(passTxt.Text) || !String.IsNullOrEmpty(domainTxt.Text))
//{
UserName = usrTxt.Text;
Password = passTxt.Text;
Domain = domainTxt.Text;
WCFTestApplication.WCFTestApplicationClient client = new WCFTestApplication.WCFTestApplicationClient();
client.ClientCredentials.Windows.ClientCredential.Domain = Domain;
client.ClientCredentials.Windows.ClientCredential.UserName = UserName;
client.ClientCredentials.Windows.ClientCredential.Password = Password;
//this part needs to be modified, so certificate can be accepted from other machines as well.
System.Net.ServicePointManager.ServerCertificateValidationCallback += (se, cert, chain, sslerror) => { return true; };
textBox1.Text = client.GetData();
client.Close();
//}
//else
//{
// MessageBox.Show("Fields like username, password and domain must not be blank...!","Warning...!",MessageBoxButtons.OK, MessageBoxIcon.Warning);
//}
}
private void domainTxt_MouseHover(object sender, EventArgs e)
{
tipLbl.Visible = true;
}
private void domainTxt_MouseLeave(object sender, EventArgs e)
{
tipLbl.Visible = false;
}
}
}
상호 작용
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace WCFTestApplication
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
[ServiceContract]
public interface IWCFTestApplication
{
[OperationContract]
string GetData();
// TODO: Add your service operations here
}
}
수업
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace WCFTestApplication
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
// NOTE: In order to launch WCF Test Client for testing this service, please select Service1.svc or Service1.svc.cs at the Solution Explorer and start debugging.
public class WCFTestApplication : IWCFTestApplication
{
public string GetData()
{
return "WCF is working, and message is authenticated and encrypted";
}
}
}
다른 사람들이 조금 공부하고 자신의 구성을 만드는 데 필요한 모든 것을 찾을 수 있도록 전체 코드를 붙여 넣었습니다. 그래서 이것은 웹 서비스에 대한 SSL, wsHttpBinding 및 Windows / NTLM 인증을 포함하는 설정입니다.
문제는 IIS 구성에 시간을 낭비하고 익명 인증을 비활성화했을 때 인증이 처음에 작동하지 않는 이유를 완전히 다른 방향으로 가고 있다는 것입니다. 문제는 전체 보안 부분이 WCF를 통해 이루어지기 때문에 IIS에 신경 쓸 필요가 없었습니다. 그래서 제가 한 것은 익명 인증을 활성화하는 것입니다. 필요한 이유가 있습니다. 이것이 없으면 클라이언트 웹 참조를 업데이트 할 수 없습니다. (적어도 나는 할 수 없었다 ...). 어 그래. 그렇다고해서 누구나 먼저 로그인하지 않고도 WCF 서비스를 사용할 수 있다는 의미는 아닙니다. 두 번째로 저를 혼란스럽게하는 것은 동일한 도메인에 있었기 때문에 익명 인증을 활성화 할 때마다 로깅 정보없이 WCF 서비스에서 결과를 얻었습니다. 클래스의 클라이언트 프록시 개체에 제공됩니다. 문제는
PS 마지막으로 클라이언트 응용 프로그램에서 코드의 일부 System.Net.ServicePointManager.ServerCertificateValidationCallback += (se, cert, chain, sslerror) => { return true; };
는 보안 지점에서 발생하는 진정한 보안 위험입니다. 도메인에없는 다른 시스템이 'server.domain'권한으로 SSL / TLS 보안 채널에 대한 신뢰 관계를 설정할 수 없기 때문에 테스트를 위해이 코드를 추가했습니다.
마지막으로 도움을 주신 모든 분들께 감사드립니다. 건배.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다