XML-RPC.NET的X509Certificates如何使用呢?
继续上一篇的问题。用起来挺简单的,但是有点麻烦的问题,也要到网上找找答案才行。
先来看实验条件(这个X509Certificates好像应该是给SSL链接的时候使用的,我就这中使用方法):
1。先看看服务器端:xampplite下的php,已经开启了SSL链接(好像是装了就有了),默认已经加载php_xmlrpc.dll模块,用这个模块php_xmlrpc的开发就简单许多了。
一个.php文件就可以了,代码如下,注解不是我写的,不知道代码在哪儿找来的。可惜服务器没有安装php_xmlrpc.dll模块,不过,还是找到了另外的php代码龌龊的实现了php的xmlrpc服务。
<?php
/**
* 函数:提供给RPC客户端调用的函数
* 参数:
* $method 客户端需要调用的函数
* $params 客户端需要调用的函数的参数数组
* 返回:返回指定调用结果
*/
function userSayHello_func($method, $params) {
$user = $params[0];
return "Hello ".$user."!";
}
//产生一个XML-RPC的服务器端
$xmlrpc_server = xmlrpc_server_create();
//注册一个服务器端调用的方法rpc_server,实际指向的是rpc_server_func函数
xmlrpc_server_register_method($xmlrpc_server, "user.SayHello", "userSayHello_func");
//接受客户端POST过来的XML数据//客户端的需要设置为text/xml
$request = $HTTP_RAW_POST_DATA;
//执行调用客户端的XML请求后获取执行结果
$xmlrpc_response = xmlrpc_server_call_method($xmlrpc_server, $request, null);
//把函数处理后的结果XML进行输出
header('Content-Type: text/xml');
echo $xmlrpc_response;
//销毁XML-RPC服务器端资源
xmlrpc_server_destroy($xmlrpc_server);
?>
简单的就是一个user.SayHello的方法,需要提供一个参数。待会儿抓包看看如何Post XML格式的数据来访问这个方法。访问一下这个php,发现错误了。server error. method not found.没有默认的方法。
2.客户端代码:先添加对CookComputing.XmlRpcV2.dll的引用
using CookComputing.XmlRpc;
using System.Security.Cryptography.X509Certificates;
using System.Net;
在命名空间下添加以下interface
[XmlRpcUrl(https://localhost/s/1.php)] //我的xml-rpc地址,注意是https的
public interface IUser : IXmlRpcProxy
{
[XmlRpcMethod("user.SayHello")]
string UserLogin(string username);
}
然后是:
IUser user = XmlRpcProxyGen.Create<IUser>();
// 打开证书存储区
X509Store store = new X509Store(StoreName.My);
store.Open(OpenFlags.ReadWrite);
// 检索证书
//X509Certificate.CreateFromCertFile("C:certificate.cer")
X509Certificate2Collection certs = store.Certificates;
System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();
user.ClientCertificates.Add(certs[0]);//没有证书的话,自己创建一个吧
MessageBox.Show(user.UserLogin(" cat").ToString());
需要的一个类:
public class TrustAllCertificatePolicy : System.Net.ICertificatePolicy
{
public TrustAllCertificatePolicy()
{ }
public bool CheckValidationResult(ServicePoint sp,
System.Security.Cryptography.X509Certificates.X509Certificate cert,
WebRequest req, int problem){
return true;
}
}
以上所需要的类参考以下内容,来自“用HttpWebRequest加载证书建立SSL通道时发生异常的解决办法”http://www.cnblogs.com/zhengyun_ustc/archive/2005/04/11/135821.html
证书标识特定的计算机,该计算机的名称位于证书的公共名称中。但是,很容易就会更改计算机的名称或使用客户端配置文件中的“localhost”,这会在客户端和服务器证书中的公共名称之间造成不匹配的情况。在 .NET Framework 1.0 版中,这一不匹配的情况将被忽略,并且将在服务器上引发调用。
从 .NET Framework 1.1 版开始,这一不匹配的情况会引发以下异常:“System.Net.WebException:基础连接已经关闭:无法与远程服务器建立信任关系”。如果您无法配置远程处理客户端以使用证书公共名称,则可以使用客户端应用程序配置文件中的以下设置重写这一不匹配的情况。
<system.net>
<settings>
<servicePointManager checkCertificateName="true" />
</settings>
</system.net>
若要以编程方式使客户端忽略证书名称不匹配,客户端必须创建一个特定类的实例,如果 certificateProblem 值为 0x800c010f,该类将实现 ICertificatePolicy 接口并实现 CheckValidationResult 方法以返回 true。然后,您必须将该对象注册到 System.Net.ServicePointManager 对象,方法是将该对象传递到 ServicePointManager.CertificatePolicy 属性。”
基本就可以加密我们的传送内容了。
抓包过程,由于这里抓的是http的post包,可以使用tcpTrace来做一个代理,然后获取到这些发送的的内容:
把xml-rpc地址换回http的,把System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();注悉掉。设定tcpTrace后,就可以清楚的得到post到服务器的xml文件了:
<?xml version="1.0"?>
<methodCall>
<methodName>user.SayHello</methodName>
<params>
<param>
<value>
<string>cat</string>
</value>
</param>
</params>
</methodCall>
也可以看到服务器返回的xml:
<?xml version="1.0" encoding="iso-8859-1"?>
<methodResponse>
<params>
<param>
<value>
<string>Hello cat!</string>
</value>
</param>
</params>
</methodResponse>
加密后的数据就是乱的,所以就不抓了。