ASMX用户名和密码安全性

8
我有一个基础的ASMX服务,正在尝试运行它(我更愿意使用WCF,但无法使服务器与它一起工作)。它在没有安全设置的情况下可以正常运行,但是一旦打开安全性,我就会收到以下错误信息:“HTTP请求未经授权,客户端身份验证方案为'匿名'。从服务器接收到的身份验证标头为“基本领域=“安全区域”。”我想要的是最简单的解决方案,即“请求用户的名称和密码”。使用Intellisense查看代码并没有找到需要的内容。这里看起来可能会有所帮助,但它似乎是关于WCF的,所以谁知道呢。
我刚意识到我可以将其制作成实时演示:
这是服务:http://smplsite.com/sandbox3/Service1.asmx 用户名为testapp,密码为testpw。我需要一个调用该服务功能的命令行应用程序。
在添加了安全性之前,在VS项目上运行添加Web服务引用 后,此行可以正常工作。
new ServiceReference1.Service1SoapClient().HelloMom("Bob");

这是我目前的尝试(这不起作用)

class Program
{
    private static bool customValidation(object s, X509Certificate c, X509Chain ch, SslPolicyErrors e)
    { return true }

    static void Main(string[] args)
    {
         // accept anything
        ServicePointManager.ServerCertificateValidationCallback += 
              new RemoteCertificateValidationCallback(customValidation);

        var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
        binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
        binding.Security.Transport.Realm = "Secured area";

        // the generated Web Service Reference class
        var client = new ServiceReference1.Service1SoapClient(
            binding,
            new EndpointAddress("https://smplsite.com/sandbox3/Service1.asmx")
            );

        client.ClientCredentials.UserName.UserName = "testapp";
        client.ClientCredentials.UserName.Password = "testpw";

        Console.WriteLine(client.HelloMom("Bob"));
    }
}

编辑:顺便说一下,这不是一个网站或在浏览器中运行,访问代码是一个C#命令行应用程序。此外,身份验证是由另一个我无法控制的IIS插件完成的。

编辑2:明确一点;我正在寻找的解决方案是纯客户端问题。

编辑3:访问控制通过.haccess类型的系统进行,我很喜欢这种方式。 我不希望服务代码执行任何身份验证。


阅读您的编辑后,我不确定我的解决方案是否有帮助,因为其他 IIS 插件正在进行身份验证。我会将其保留在那里,以防它能够引发灵感... - Moose
我已经编辑了我的回答。我不知道那是否有帮助,但这是另一次尝试... - Moose
你能否使用浏览器访问你的 Web 服务,并使用 Fiddler 观察发送给它的内容?然后,你可以尝试复制浏览器使用的身份验证。否则,我就没什么办法了。 - Moose
太复杂了,我没有能力做一些拼凑在一起的东西。 - BCS
你能通过网页浏览器进入吗? - BCS
显示剩余2条评论
3个回答

12

编辑:
使用这个怎么样:

MyWebService svc = new MyWebService();            
svc.Credentials = new System.Net.NetworkCredential(UserID, pwd);
bool result = svc.MyWebMethod();    

楼主说这个方法不行,在他的情况下确实是不行。

我们通常会采用这种方式:

public class MyWebService : System.Web.Services.WebService
{
    public AuthenticationHeader AuthenticationInformation;

    public class AuthenticationHeader : SoapHeader
    {
        public string UserName;
        public string Password;
    }

    [WebMethod( Description = "Sample WebMethod." )]
    [SoapHeader( "AuthenticationInformation" )]
    public bool MyWebMethod()
    {
        if ( AuthenticationInformation != null )
        {
            if ( IsUserAuthenticated( AuthenticationInformation.UserName,   
                 AuthenticationInformation.Password, ref errorMessage ) )
            {
                 // Authenticated, do something
            }
            else
            {
                 // Failed Authentication, do something
            } 
        }
        else
        {
                 // No Authentication, do something
        }
    }
}
注意要提供 IsUserAuthenticated() 方法。
然后客户端这样调用它:
 MyWebService svc = new MyWebService();            
 svc.AuthenticationHeaderValue = new MyWebService.AuthenticationHeader();
 svc.AuthenticationHeaderValue.UserName = UserID;
 svc.AuthenticationHeaderValue.Password = Password;

 bool result = svc.MyWebMethod();

不好意思,那个不能满足我的需求:据我所知,IIS 在我的代码开始运行之前就拒绝了访问尝试。我认为(并希望)它正在使用与静态内容访问控制相同类型的机制。 - BCS
那么,使用您的 Web 服务对象的凭据属性怎么样? - Moose
谢谢,这个AuthenticationHeader的想法对我很有帮助。唯一的问题是我无法访问svc.AuthenticationHeaderValue。最终我只能调用result = svc.MyWebMethod(authHeader); - deanis

2

配置:

<binding name="MyBinding" closeTimeout="00:00:30"
      openTimeout="00:00:30" receiveTimeout="00:00:30" sendTimeout="00:00:30"
      allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
      maxBufferPoolSize="524288" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"
      textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true"
      messageEncoding="Text">
      <readerQuotas maxDepth="32" maxStringContentLength="2147483647"
        maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
      <security mode="Transport">
        <transport clientCredentialType="Basic" realm=""/>
      </security>
    </binding>
  </basicHttpBinding>

在使用时

proxy.ClientCredentials.UserName.UserName = userName;
proxy.ClientCredentials.UserName.Password = password;

这对我来说完全没问题。

2

听起来很有前途,但似乎没有GetWebRequest方法可供覆盖 :( - BCS
我无法查看您的Web服务以查看其类,但我查看了我在此处使用的一个。它的基类是System.Web.Services.Protocols.SoapHttpClientProtocol,其中包含一个受保护的重写方法System.Net.WebRequest GetWebRequest(System.Uri uri)。这就是您需要覆盖的方法,对吗? - Moose

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接