对 Wcf 服务的调用被拒绝?这是网络配置的问题吗?

发布于 2024-10-14 07:51:38 字数 4553 浏览 8 评论 0原文

我有一个 WCF 服务...它将驻留在 Azure 上。我通过 web.config 中的以下配置添加了表单身份验证和授权:

<system.web>
        <compilation debug="true" targetFramework="4.0" />
        <authentication mode="Forms">
            <forms loginUrl="blah.svc" timeout="2880" />
        </authentication>
        <membership defaultProvider="SqlMembershipProvider">
            <providers>
                <add connectionStringName="blah" applicationName="blah_app" name="SqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" />
            </providers>
        </membership>
        <profile>
            <providers>
                <add name="SqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="blah" applicationName="blah_app" />
            </providers>
        </profile>
        <roleManager enabled="true" defaultProvider="SqlRoleProvider">
            <providers>
                <add connectionStringName="blah" applicationName="blah_app" name="SqlRoleProvider" type="System.Web.Security.SqlRoleProvider" />
            </providers>
        </roleManager>
    </system.web>
    <system.serviceModel>
        <behaviors>
            <serviceBehaviors>
                <behavior name="wsHttp">
                    <serviceMetadata httpGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="false" />
                    <serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="SqlRoleProvider" />
                    <serviceCredentials>
                        <serviceCertificate x509FindType="FindBySubjectName" storeName="My" storeLocation="LocalMachine" findValue="blah_cert" />
                    </serviceCredentials>

                </behavior>
            </serviceBehaviors>
        </behaviors>
        <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
        <services>
            <service name="blah_app.blah" behaviorConfiguration="wsHttp">
                <endpoint address="" contract="blah_app.iblah" binding="wsHttpBinding" />
            </service>
        </services>
    </system.serviceModel>

我遇到的问题是客户端对 Web 服务的任何调用都被拒绝!

public class Blah:IBlah
{
[PrincipalPermission(SecurityAction.Demand, Role = "BlahOppRole")]
        public BlahResponse Blah(BlahRequest BlahRequest)
        {
            BlahResponse = new BlahResponse();


            return response;
        }
}

我的客户端是一个 Windows 控制台应用程序。它具有以下配置:

<system.serviceModel>
        <bindings>
            <wsHttpBinding>
                <binding name="WSHttpBinding_IBlah" closeTimeout="00:01:00"
                    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                    bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                    maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                    messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
                    allowCookies="false">
                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                    <reliableSession ordered="true" inactivityTimeout="00:10:00"
                        enabled="false" />
                    <security mode="Message">
                        <transport clientCredentialType="Digest" proxyCredentialType="None"
                            realm="" />
                        <message clientCredentialType="UserName" negotiateServiceCredential="true"
                            algorithmSuite="Default" />
                    </security>
                </binding>
            </wsHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://127.0.0.1:89/Blah.svc"
                binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IBlah"
                contract="Data.Blah" name="WSHttpBinding_IBlah">
                <identity>
                    <dns value="blah_cert"/>
                </identity>
            </endpoint>
        </client>

I have a WCF service... which will reside on Azure. I added forms authentication and authorization via the following configuration in the web.config:

<system.web>
        <compilation debug="true" targetFramework="4.0" />
        <authentication mode="Forms">
            <forms loginUrl="blah.svc" timeout="2880" />
        </authentication>
        <membership defaultProvider="SqlMembershipProvider">
            <providers>
                <add connectionStringName="blah" applicationName="blah_app" name="SqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" />
            </providers>
        </membership>
        <profile>
            <providers>
                <add name="SqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="blah" applicationName="blah_app" />
            </providers>
        </profile>
        <roleManager enabled="true" defaultProvider="SqlRoleProvider">
            <providers>
                <add connectionStringName="blah" applicationName="blah_app" name="SqlRoleProvider" type="System.Web.Security.SqlRoleProvider" />
            </providers>
        </roleManager>
    </system.web>
    <system.serviceModel>
        <behaviors>
            <serviceBehaviors>
                <behavior name="wsHttp">
                    <serviceMetadata httpGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="false" />
                    <serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="SqlRoleProvider" />
                    <serviceCredentials>
                        <serviceCertificate x509FindType="FindBySubjectName" storeName="My" storeLocation="LocalMachine" findValue="blah_cert" />
                    </serviceCredentials>

                </behavior>
            </serviceBehaviors>
        </behaviors>
        <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
        <services>
            <service name="blah_app.blah" behaviorConfiguration="wsHttp">
                <endpoint address="" contract="blah_app.iblah" binding="wsHttpBinding" />
            </service>
        </services>
    </system.serviceModel>

the problem I am getting is that any of the calls to the web service from the client are comming as Denied!

public class Blah:IBlah
{
[PrincipalPermission(SecurityAction.Demand, Role = "BlahOppRole")]
        public BlahResponse Blah(BlahRequest BlahRequest)
        {
            BlahResponse = new BlahResponse();


            return response;
        }
}

My client is a windows console app. It has the following configuration:

<system.serviceModel>
        <bindings>
            <wsHttpBinding>
                <binding name="WSHttpBinding_IBlah" closeTimeout="00:01:00"
                    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                    bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                    maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                    messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
                    allowCookies="false">
                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                    <reliableSession ordered="true" inactivityTimeout="00:10:00"
                        enabled="false" />
                    <security mode="Message">
                        <transport clientCredentialType="Digest" proxyCredentialType="None"
                            realm="" />
                        <message clientCredentialType="UserName" negotiateServiceCredential="true"
                            algorithmSuite="Default" />
                    </security>
                </binding>
            </wsHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://127.0.0.1:89/Blah.svc"
                binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IBlah"
                contract="Data.Blah" name="WSHttpBinding_IBlah">
                <identity>
                    <dns value="blah_cert"/>
                </identity>
            </endpoint>
        </client>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

扶醉桌前 2024-10-21 07:51:38

这篇 MSDN 文章 提供了有关如何使用用户名身份验证配置 WsHttpBinding。

基本上,您必须将

  • 安全模式设置为 TransportWithMessageCredential (步骤 6)
  • 添加 ServiceCredentials 服务行为并配置 userNameAuthentication (步骤 8)
  • 修改您的客户端应用程序设置用户名和密码(步骤 12)

This MSDN article gives a good step-by-step instruction on how to configure WsHttpBinding with UserName authentication.

Basically you will have to

  • Set security mode to TransportWithMessageCredential (Step 6)
  • Add a ServiceCredentials service behavior and configure userNameAuthentication (Step 8)
  • Modify your Client application to set the UserName and Password (Step 12)
如果没结果 2024-10-21 07:51:38

出色地,
由于我使用的是自签名证书...客户对该证书的真实性大发雷霆。常见错误是 AccessDenied(由于服务配置错误),以及“协商服务凭证时发生错误...”或类似的错误。长话短说,在阅读了这个好人的帖子后(谢谢 Dev @ Work)Dev @ Work 我能够修改他的工作并通过服务上的成员资格和角色提供程序添加 ASP.NET 表单身份验证和授权。

总而言之,Dev @ Work 的观点非常有道理。 WCF 客户端会对自签名证书大喊大叫。使 wcf 服务在开发服务器上发挥作用的技巧是向服务客户端撒谎,告知用于对客户端凭据进行编码的证书的真实性。为此,任何 wcf 客户端都必须为其 serviceEndpoint 提供 behaviorConfiguration,并使用自定义证书验证机制来验证服务器的证书。这是通过创建一个继承自 System.IdentityModel.Selectors.X509CertificateValidator 的对象并重写该对象的 Validate() 方法来完成的。如果所述对象不抛出错误,则验证成功:

<client>
            <endpoint address="http://machine:5101/blah.svc"
                binding="wsHttpBinding" bindingConfiguration="WsHttpBinding_Iblah"
                contract="Data.Iblah" name="WsHttpBinding_Iblah" behaviorConfiguration="BehaviorConfig">
                <identity>
                    <certificate encodedValue="..." />
                </identity>
            </endpoint>
        </client>

        <behaviors>
            <endpointBehaviors>
                <behavior name="BehaviorConfig">
                    <clientCredentials>
                        <serviceCertificate>
                            <authentication certificateValidationMode="Custom" customCertificateValidatorType="BlahConsole.X509Validator, BlahConsole"/>
                        </serviceCertificate>
                    </clientCredentials>        
                </behavior>
            </endpointBehaviors>
        </behaviors>

自定义验证器:

internal class X509Validator : System.IdentityModel.Selectors.X509CertificateValidator
    {
        public override void Validate(X509Certificate2 certificate)
        {
            // validate argument
            if (certificate == null)
                throw new ArgumentNullException("Certificate is null");
        }
    }

Well,
Since I was using a self signed certificate... the client was throwing a fit about the authenticity of that certificate. Common errors were AccessDenied, (due to misconfiguration of the service), as well "Error occured while negotiating the service credential..." or something along the lines. Long story short, after reading the post of this fine fellow (Thank you Dev @ Work) Dev @ Work I was able to modify his work and add ASP.NET forms authentication and authorization via Membership and Role providers on the service.

To sum it up, Dev @ Work had a very valid point. WCF clients will scream about self signed certificates. The trick to making a wcf service useful on a dev server is to lie to the service clients about the authenticity of the certificate used to encode the client's credentials. To do so, any wcf client has to have a behaviorConfiguration to its serviceEndpoint and use custom certificate validation mechanism to authenticate the server's certificate. This is done by creating an object that inherits from the System.IdentityModel.Selectors.X509CertificateValidator and by overriding the Validate() method of said object. The validation is successful if the said object doesn't throw errors:

<client>
            <endpoint address="http://machine:5101/blah.svc"
                binding="wsHttpBinding" bindingConfiguration="WsHttpBinding_Iblah"
                contract="Data.Iblah" name="WsHttpBinding_Iblah" behaviorConfiguration="BehaviorConfig">
                <identity>
                    <certificate encodedValue="..." />
                </identity>
            </endpoint>
        </client>

        <behaviors>
            <endpointBehaviors>
                <behavior name="BehaviorConfig">
                    <clientCredentials>
                        <serviceCertificate>
                            <authentication certificateValidationMode="Custom" customCertificateValidatorType="BlahConsole.X509Validator, BlahConsole"/>
                        </serviceCertificate>
                    </clientCredentials>        
                </behavior>
            </endpointBehaviors>
        </behaviors>

And the custom validator:

internal class X509Validator : System.IdentityModel.Selectors.X509CertificateValidator
    {
        public override void Validate(X509Certificate2 certificate)
        {
            // validate argument
            if (certificate == null)
                throw new ArgumentNullException("Certificate is null");
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文