[英]Mono C# HTTPs (XMLRPC.NET) failure : client certificate or server certificate issue?
[英]Implementation of C# XMLRPC.NET client and server over HTTPS
很難找到與https一起使用的XMLRPC.net庫的信息。
可以設置“https”URL的唯一文檔是: http : //xml-rpc.net/faq/xmlrpcnetfaq-2-5-0.html#2.3但是它沒有准確解釋如何正確設置。
在下載http://xmlrpcnet.googlecode.com/files/xml-rpc.net.2.5.0.zip中提供的樣本基礎上試驗我試過這個:
StateNameServer解決方案的client.cs文件中的更改:
IStateName svr = (IStateName)Activator.GetObject(
typeof(IStateName), "https://localhost:5678/statename.rem");
服務器代碼是什么樣的
IDictionary props = new Hashtable();
props["name"] = "MyHttpChannel";
props["port"] = 5678;
HttpChannel channel = new HttpChannel(
props,
null,
new XmlRpcServerFormatterSinkProvider()
);
ChannelServices.RegisterChannel(channel, false);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(StateNameServer),
"statename.rem",
WellKnownObjectMode.Singleton);
當嘗試使用HTTPS聯系服務器時,客戶端顯然會丟棄異常,因為我不知道如何配置它。 無論如何,有人可以幫忙嗎? 我應該尋找什么樣的東西?
非常感謝 !
首先,我要熱烈感謝Charles Cook對此問題的幫助以及開發XMLRPC.NET。
其次,此示例基於可在此處下載的XMLRPC.NET StateNameServer示例: http ://xml-rpc.net/download.html
所以這是解決方案:
1.生成或獲取[自簽名]證書(例如使用makecert.exe)
2.將此證書添加到服務器配置中,並使用httpcfg.exe或其他工具(如HttpSysConfig (開源))指定要與XMLRPC.NET服務器(在本例中為5678)一起使用的端口
3.使用以下代碼實現XMLRPC.NET服務器:
using System;
using System.Collections;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using CookComputing.XmlRpc;
using System.Net;
using System.IO;
public class _
{
static void Main(string[] args)
{
HttpListener listener = new HttpListener();
listener.Prefixes.Add("https://127.0.0.1:5678/");
listener.Start();
while (true)
{
HttpListenerContext context = listener.GetContext();
ListenerService svc = new StateNameService();
svc.ProcessRequest(context);
}
Console.WriteLine("Press <ENTER> to shutdown");
Console.ReadLine();
}
}
public class StateNameService : ListenerService
{
[XmlRpcMethod("examples.getStateName")]
public string GetStateName(int stateNumber)
{
if (stateNumber < 1 || stateNumber > m_stateNames.Length)
throw new XmlRpcFaultException(1, "Invalid state number");
return m_stateNames[stateNumber - 1];
}
string[] m_stateNames
= { "Alabama", "Alaska", "Arizona", "Arkansas",
"California", "Colorado", "Connecticut", "Delaware", "Florida",
"Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa",
"Kansas", "Kentucky", "Lousiana", "Maine", "Maryland", "Massachusetts",
"Michigan", "Minnesota", "Mississipi", "Missouri", "Montana",
"Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico",
"New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma",
"Oregon", "Pennsylviania", "Rhose Island", "South Carolina",
"South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia",
"Washington", "West Virginia", "Wisconsin", "Wyoming" };
}
public abstract class ListenerService : XmlRpcHttpServerProtocol
{
public virtual void ProcessRequest(HttpListenerContext RequestContext)
{
try
{
IHttpRequest req = new ListenerRequest(RequestContext.Request);
IHttpResponse resp = new ListenerResponse(RequestContext.Response);
HandleHttpRequest(req, resp);
RequestContext.Response.OutputStream.Close();
}
catch (Exception ex)
{
// "Internal server error"
RequestContext.Response.StatusCode = 500;
RequestContext.Response.StatusDescription = ex.Message;
}
}
}
public class ListenerRequest : CookComputing.XmlRpc.IHttpRequest
{
public ListenerRequest(HttpListenerRequest request)
{
this.request = request;
}
public Stream InputStream
{
get { return request.InputStream; }
}
public string HttpMethod
{
get { return request.HttpMethod; }
}
private HttpListenerRequest request;
}
public class ListenerResponse : CookComputing.XmlRpc.IHttpResponse
{
public ListenerResponse(HttpListenerResponse response)
{
this.response = response;
}
string IHttpResponse.ContentType
{
get { return response.ContentType; }
set { response.ContentType = value; }
}
TextWriter IHttpResponse.Output
{
get { return new StreamWriter(response.OutputStream); }
}
Stream IHttpResponse.OutputStream
{
get { return response.OutputStream; }
}
int IHttpResponse.StatusCode
{
get { return response.StatusCode; }
set { response.StatusCode = value; }
}
string IHttpResponse.StatusDescription
{
get { return response.StatusDescription; }
set { response.StatusDescription = value; }
}
private HttpListenerResponse response;
}
public class StateNameServer : MarshalByRefObject, IStateName
{
public string GetStateName(int stateNumber)
{
if (stateNumber < 1 || stateNumber > m_stateNames.Length)
throw new XmlRpcFaultException(1, "Invalid state number");
return m_stateNames[stateNumber-1];
}
public string GetStateNames(StateStructRequest request)
{
if (request.state1 < 1 || request.state1 > m_stateNames.Length)
throw new XmlRpcFaultException(1, "State number 1 invalid");
if (request.state2 < 1 || request.state2 > m_stateNames.Length)
throw new XmlRpcFaultException(1, "State number 1 invalid");
if (request.state3 < 1 || request.state3 > m_stateNames.Length)
throw new XmlRpcFaultException(1, "State number 1 invalid");
string ret = m_stateNames[request.state1-1] + " "
+ m_stateNames[request.state2-1] + " "
+ m_stateNames[request.state3-1];
return ret;
}
string[] m_stateNames
= { "Alabama", "Alaska", "Arizona", "Arkansas",
"California", "Colorado", "Connecticut", "Delaware", "Florida",
"Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa",
"Kansas", "Kentucky", "Lousiana", "Maine", "Maryland", "Massachusetts",
"Michigan", "Minnesota", "Mississipi", "Missouri", "Montana",
"Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico",
"New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma",
"Oregon", "Pennsylviania", "Rhose Island", "South Carolina",
"South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia",
"Washington", "West Virginia", "Wisconsin", "Wyoming" };
}
4.使用以下代碼實現XMLRPC.NET客戶端(代碼還創建新的X509客戶端證書)
using System;
using System.Collections;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using CookComputing.XmlRpc;
using System.Net;
using System.Security.Cryptography.X509Certificates;
class _
{
public class TrustAllCertificatePolicy : System.Net.ICertificatePolicy
{
public TrustAllCertificatePolicy() { }
public bool CheckValidationResult(ServicePoint sp,
X509Certificate cert,
WebRequest req,
int problem)
{
return true;
}
}
static void Main(string[] args)
{
System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();
IStateName proxy = XmlRpcProxyGen.Create<IStateName>();
XmlRpcClientProtocol cp = (XmlRpcClientProtocol)proxy;
cp.Url = "https://127.0.0.1:5678/";
cp.ClientCertificates.Add(new System.Security.Cryptography.X509Certificates.X509Certificate(@"C:\path\to\your\certificate\file\my.cer"));
cp.KeepAlive = false;
//cp.Expect100Continue = false;
//cp.NonStandard = XmlRpcNonStandard.All;
string stateName = ((IStateName)cp).GetStateName(13);
}
}
當然,我不在這里給出ServerStateName的接口實現,但你可以使用頂部的下載鏈接在示例文件中找到它。
備注 :
System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy()
; 將允許服務器實現接受您自己生成的自簽名證書。 我認為證書頒發機構頒發的證書不需要這樣做。
如果您發現任何可以改進的內容並且不正確,我們將不勝感激。
使用XmlRpcProxyGen.Create創建客戶端代理,指定https url(您的接口應該從IXmlRpcProxy派生)。 如果需要提供客戶端證書,則代理具有ClientCertificates屬性,該屬性的使用方式與System.Net.HttpWebRequest類中的相應屬性相同。
我不認為Remoting可以支持HTTPS。 您可以使用XML-RPC.NET FAQ中描述的HttpListener,但您需要配置證書,例如本博客中所述
好文章! 幫助了我很多。 但是第1項和第2項花了我一天才弄明白。 所以這是我的經驗:
netsh http add sslcert ipport=192.168.111.195:4022 certhash=c8973a86141a7a564a6f509d1ecfea326a1852a2 appid={0a582a74-fc2d-476c-9281-c73b2e4bfb26}
,其中'ipport'是將使用的ip / port對用於ssl連接; 'certhash'是證書哈希(您在上一步中創建的開放證書 - >轉到詳細信息 - >查找Thumbprint); 'appid'可以是任何。 如果您在HttpListener URL中指定“https”,則此類將自動查找綁定證書。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.