码迷,mamicode.com
首页 > 其他好文 > 详细

对有ssl验证的Soap请求进行提交和获取响应

时间:2015-03-11 19:30:10      阅读:3123      评论:0      收藏:0      [点我收藏+]

标签:

最近一段时间做了一个项目,需要将生成的soap请求的xml字符串提交给服务端地址,然后将返回的soap响应进行分析判断得到结果。这其中需要在请求的同时附上证书进行验证。

 

其实这个功能实现起来不是很难,但是在研究的过程中有几个小问题却让我多费了好几个脑细胞,在此记录下,为自己和博友们做一下小小的提醒。

其中主要出现的问题有以下几点:

  •   报WebException异常: The request was aborted: Could not create SSL/TLS secure channel.
  •   报服务器内部500错误

这两个问题主要在代码中哪些部分会出现呢,就去代码中看看。

 

OK,先上段代码

 1         /// <summary>
 2         /// 进行进行ssl验证的服务器进行soap请求
 3         /// </summary>
 4         /// <param name="tokenId">需要生成soap请求的参数1</param>
 5         /// <param name="secureCode">需要生成soap请求的参数2</param>
 6         /// <returns>soap请求的响应内容</returns>
 7         public string SoapRequest(string tokenId, string secureCode)
 8         {
 9             string url = "https://[The request url for your soap request]";
10             string soapAction = "[the action name]";
11 
12             // GenerateSoapContent 方法用来构造Soap的XML请求
13             string soapRequest = GenerateSoapContent(tokenId, secureCode);
14 
15             // 这句话用来调用ValidateFbCertificate方法,让远程ssl证书验证设为成功
16             ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateFbCertificate);
17 
18             // 设置安全协议类型,这个需要对应具体需求
19             ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
20 
21             HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
22             webRequest.Headers.Add("SOAPAction", soapAction);
23             webRequest.ContentLength = soapRequest.Length;
24             webRequest.Method = "POST";
25             webRequest.ProtocolVersion = HttpVersion.Version10;
26 
27             // 将证书加入web请求中
28             X509Certificate2 cert2 = new X509Certificate2(Server.MapPath("pfx或者p12格式的文件名"), "证书密码", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
29             webRequest.ClientCertificates.Add(cert2);
30 
31             using (Stream requestStream = webRequest.GetRequestStream())
32             {
33                 byte[] paramBytes = Encoding.UTF8.GetBytes(soapRequest);
34                 requestStream.Write(paramBytes, 0, paramBytes.Length);
35                 requestStream.Close();
36             }
37 
38             WebResponse webResponse = null;
39             try
40             {
41                 webResponse = webRequest.GetResponse();
42                 using (StreamReader myReader = new StreamReader(webResponse.GetResponseStream(), Encoding.UTF8))
43                 {
44                     string response = myReader.ReadToEnd();
45                     myReader.Close();
46                     return response;
47                 }
48             }
49             catch (Exception ex)
50             {
51                 throw ex;
52             }
53         }
54 
55         /// <summary>
56         /// Generate the soap request
57         /// </summary>
58         /// <param name="userId">the token Id</param>
59         /// <param name="secureCode">the secure code</param>
60         /// <returns>the request string</returns>
61         string GenerateSoapContent(string userId, string secureCode)
62         {
63             return "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:vip=\"https://schemas.symantec.com/vip/2011/04/vipuserservices\">"
64                 + "<soapenv:Header/>"
65                 + "<soapenv:Body>"
66                 + "<vip:AuthenticateUserRequest>"
67                 + "<vip:requestId>1323</vip:requestId>"
68                 + "<vip:userId>" + userId + "</vip:userId>"
69                 + "<vip:otpAuthData>"
70                 + "<vip:otp>" + secureCode + "</vip:otp>"
71                 + "</vip:otpAuthData>"
72                 + "</vip:AuthenticateUserRequest>"
73                 + "</soapenv:Body>"
74                 + "</soapenv:Envelope>";
75         }

 

 

以上是基本已经将问题解决的代码。

在代码中,当16,19行代码未写,可能就会出现异常: “The request was aborted: Could not create SSL/TLS secure channel.”。当28,29行未写,那肯定会出现该异常。

在出现500内部错误时,我一直以为是服务器端的方法出现了错误,直到用php的curl执行soap请求成功返回结果,才发现是一个小小的问题导致了这个“严重”的麻烦。具体原因是因为在写soap请求文本时,原来的GenerateSoapContent方法是如下写法:

 1         /// <summary>
 2         /// Generate the soap request
 3         /// </summary>
 4         /// <param name="userId">the token Id</param>
 5         /// <param name="secureCode">the secure code</param>
 6         /// <returns>the request string</returns>
 7         string GenerateSoapContent(string userId, string secureCode)
 8         {
 9             StringBuilder builder = new StringBuilder();
10             builder.AppendLine("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
11             builder.AppendLine("<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\" >");
12             builder.AppendLine("    <S:Body>");
13             builder.AppendLine("        <AuthenticateUserRequest xmlns=\"https://schemas.vip.symantec.com\">");
14             builder.AppendLine("            <requestId>" + ((Int32)(new Random().NextDouble() * 1000) + 1) + "</requestId>");
15             builder.AppendLine("            <userId>" + userId + "</userId>");
16             builder.AppendLine("            <pin></pin>");
17             builder.AppendLine("            <otpAuthData>");
18             builder.AppendLine("            <otp>" + secureCode + "</otp>");
19             builder.AppendLine("            </otpAuthData>");
20             builder.AppendLine("        </AuthenticateUserRequest>");
21             builder.AppendLine("    </S:Body>");
22             builder.AppendLine("</S:Envelope>");
23             return builder.ToString();
24         }

看出与最上面的方法有什么不同了吗?是的,StringBuilder的AppendLine害了我,因为这样会在最终生成的soap字符串中添加了“\r\n"字符,那传到服务器端就不会被服务器端方法识别为soap的xml格式,就会抛出异常。

 

其实这些都不是什么难以解决的问题,主要是因为自己不注意。在此留下这篇文章,为后来人提供些许帮助。

 

对有ssl验证的Soap请求进行提交和获取响应

标签:

原文地址:http://www.cnblogs.com/edingod/p/4330446.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!