我的程序是c/s的,我在网上查的需要在配置文件中添加
<System.web>
<webServices>
<soapExtensionTypes>
<add type="ClassLibrary1.Class1,ClassLibrary1" group="Low " priority="1"/>
</soapExtensionTypes>
</webServices>
</System.web>
添加后,服务器端调用SOAP扩展类,但是客户端不调用。是不是C/S结构里面配置<System.web>是没有用的啊
ps:我想通过SOAP扩展对消息进行加密签名,所以两端都需要进行,现在问题是,客户端不加密,可是服务器端要加密,导致程序出错,拜托了,园子里的高手指教,谢谢了!
首先您要么客户端加密服务器端解密,要么客户端解密服务器端加密;这些加密和解密应该实现在具体的soap扩展类,服务器端是有这个配置文件,客户端并不需要Web.config, 客户端可以通过添加web service引用生成代理类,代理类中的适当地方应该添加 具体的soapExtention特性,比如[TraceExtension(file="...", priority=1)]。客户端还应该引用您的具体的soap扩展类。
您好,谢谢你的回答。我在客户端添加webservice引用了,soap扩展类我也已经写好了,在这个类里面也写了加密解密的代码,但就是不知道客户端应该怎么调用。请你能详细说一下“代理类的适当地方添加”是什么地方?[TraceExtension(file="...", priority=1)],这句话又再哪添加呢?谢谢了,拜托,我做毕设,拜托了
@灰灰快跑: <soapExtensionTypes>这个节点我没有用! 直接在代码中硬写入了。不知道怎么用,汗! 我的例子:
Web服务类:
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Services;
namespace SoapExtensionService
{
///<summary>
/// Service1 的摘要说明
///</summary>
[WebService(Namespace = "http://tempuri.org/")]
public class SoapExtensionService : System.Web.Services.WebService
{
[WebMethod]
[CryptExtension(Decrypt=DecryptModes.Request,Encrypt=EncryptModes.Response)]
public bool Login(string username, string password)
{
return "admin" == username && "12345" == password;
}
}
}
然后是扩展类:
using System;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Xml;
using System.Text;
// Define a SOAP Extension that traces the SOAP request and SOAP
// response for the XML Web service method the SOAP extension is
// applied to.
public enum EncryptModes {Request, Response, None};
public enum DecryptModes {Request, Response, None};
public class CryptExtension : SoapExtension
{
Stream oldStream;
Stream newStream;
EncryptModes encryptMode;
DecryptModes decryptMode;
public override Stream ChainStream( Stream stream ){
oldStream = stream;
newStream = new MemoryStream();
return newStream;
}
public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
{
return attribute as CryptExtensionAttribute;
}
//在使用Web.confing中的soapExtensions节时需要实现,因为扩展设置写在代码中,所以没有实现
public override object GetInitializer(Type serviceType)
{
throw new NotImplementedException();
}
public override void Initialize(object initializer)
{
CryptExtensionAttribute cea = initializer as CryptExtensionAttribute;
encryptMode = cea.Encrypt;
decryptMode = cea.Decrypt;
}
// If the SoapMessageStage is such that the SoapRequest or
// SoapResponse is still in the SOAP format to be sent or received,
// save it out to a file.
public override void ProcessMessage(SoapMessage message)
{
switch (message.Stage) {
case SoapMessageStage.BeforeSerialize:
break;
case SoapMessageStage.AfterSerialize:
Encrypt();
break;
case SoapMessageStage.BeforeDeserialize:
Decrypt();
break;
case SoapMessageStage.AfterDeserialize:
break;
default:
throw new Exception("invalid stage");
}
}
private void Encrypt()
{
newStream.Position = 0;
if (encryptMode == EncryptModes.Request || encryptMode == EncryptModes.Response)
Copy(EncryptSoap(newStream), oldStream);
else
Copy(newStream, oldStream);
}
public MemoryStream EncryptSoap(Stream streamToEncrypt)
{
streamToEncrypt.Position = 0;
XmlTextReader reader = new XmlTextReader(streamToEncrypt);
XmlDocument dom = new XmlDocument();
dom.Load(reader);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(dom.NameTable);
nsmgr.AddNamespace("soap",
"http://schemas.xmlsoap.org/soap/envelope/");
XmlNode node = dom.SelectSingleNode("//soap:Body", nsmgr);
foreach (XmlNode nodex in node.FirstChild.ChildNodes)
nodex.InnerText = Encrypt(nodex.InnerText);
MemoryStream ms = new MemoryStream();
dom.Save(ms);
ms.Position = 0;
return ms;
}
private void Decrypt()
{
if (decryptMode == DecryptModes.Request || decryptMode == DecryptModes.Response)
Copy(DecryptSoap(oldStream), newStream);
else
Copy(oldStream, newStream);
newStream.Position = 0;
}
private MemoryStream DecryptSoap(Stream streamToDecrypt)
{
XmlTextReader reader = new XmlTextReader(streamToDecrypt);
XmlDocument dom = new XmlDocument();
dom.Load(reader);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(dom.NameTable);
nsmgr.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/");
XmlNode node = dom.SelectSingleNode("//soap:Body", nsmgr);
foreach (XmlNode nodex in node.FirstChild.ChildNodes)
nodex.InnerText = Decrypt(nodex.InnerText);
MemoryStream ms = new MemoryStream();
dom.Save(ms);
ms.Position = 0;
return ms;
}
private string Encrypt(string stringToEncrypt)
{
char[] charArray = stringToEncrypt.ToCharArray();
Array.Reverse(charArray);
return new string(charArray);
}
private string Decrypt(string stringToDecrypt)
{
return Encrypt(stringToDecrypt);
}
void Copy(Stream from, Stream to)
{
TextReader reader = new StreamReader(from);
TextWriter writer = new StreamWriter(to);
writer.WriteLine(reader.ReadToEnd());
writer.Flush();
}
}
[AttributeUsage(AttributeTargets.Method)]
public class CryptExtensionAttribute : SoapExtensionAttribute {
private int priority;
private EncryptModes encrypt = EncryptModes.None;
private DecryptModes decrypt = DecryptModes.None;
public override Type ExtensionType {
get { return typeof(CryptExtension); }
}
public override int Priority {
get { return priority; }
set { priority = value; }
}
public EncryptModes Encrypt
{
get { return encrypt; }
set { encrypt = value; }
}
public DecryptModes Decrypt
{
get { return decrypt; }
set { decrypt = value; }
}
}
然后是客户端的代理类(Reference.cs)中:
///<remarks/>
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/Login", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
[CryptExtension(Encrypt=EncryptModes.Request,Decrypt=DecryptModes.Response)]
public bool Login(string username, string password) {
object[] results = this.Invoke("Login", new object[] {
username,
password});
return ((bool)(results[0]));
}
调试好这个soap扩展类有点不容易啊!
就是你的soap扩展attribute类中指定了特性的[AttributeUsage(AttributeTargets.Method)]写的地方是Method, 那么就写在Method上面了!
不知道,怎么加密解密,就用Reverse了;要用我的代码,把Web.Config中的<soapExtensionTypes>这节去掉。
@ChatinCode: 您好,非常感谢您的回复。服务器端调用SOAP扩展有两种方法,一种就是您上面说的通过[webmethod];另一种就是我写的通过配置文件。可是,我的问题是,如何是客户端进行SOAP扩展呢?
ps:SOAP扩展类我都写好了,加密解密方法我也都写好了,服务器端能够正常调用SOAP扩展类,但是客户端应该如何做才能正常调用呢?拜托了,谢谢您
@ChatinCode:
@灰灰快跑: 哎呀,你要实现你自己的Attribute类,我的代码中是这个类,
[AttributeUsage(AttributeTargets.Method)]
public class CryptExtensionAttribute : SoapExtensionAttribute
在使用这个Attribute的时候,把后面的类名去掉后面的Attribute,然后写在方括号里面,然后把要赋值的属性写在小括号里面
[CryptExtension(Encrypt=EncryptModes.Request,Decrypt=DecryptModes.Response)]
上面的小括号里面 Encrypt,和Decrypt是那个CryptExtensionAttribute的Property啊,怎么会搞不明白,这样就会把这个特性(Attribute)应用到客户端的那个代理类的方法上面去了,[]里面是一个Attribute,就跟你[WebMethod...]一样是个特性,怎么会不明白呢?
@灰灰快跑: 如果不写这个Attribute, 客户端没办法调用那个SoapExtension中的代码的!
@ChatinCode: 我写了,可是客户端就是不执行怎么办??呜呜呜呜~~~~~~~~~~~
@ChatinCode: 我有自己的Attribute类,也在客户端代理类中按您说的添加了可就是不行啊,客户端就是不执行SOAP扩展,我的客户端是窗体用用程序
@灰灰快跑:阿妹啊,把你的代码贴出来吧,要不你仔细研究一下我的程序,或者别的例子。
@灰灰快跑: 我说的客户端代理类是指你添加 "Web引用" 自动生成的类,你的是什么呀??我的代理类的代码:
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.239
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
//
// 此源代码是由 Microsoft.VSDesigner 4.0.30319.239 版自动生成。
//
#pragma warning disable 1591
namespace TestExtension.chatincode {
using System;
using System.Web.Services;
using System.Diagnostics;
using System.Web.Services.Protocols;
using System.ComponentModel;
using System.Xml.Serialization;
///<remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.1")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Web.Services.WebServiceBindingAttribute(Name="SoapExtensionServiceSoap", Namespace="http://tempuri.org/")]
public partial class SoapExtensionService : System.Web.Services.Protocols.SoapHttpClientProtocol {
private System.Threading.SendOrPostCallback LoginOperationCompleted;
private bool useDefaultCredentialsSetExplicitly;
///<remarks/>
public SoapExtensionService() {
this.Url = global::TestExtension.Properties.Settings.Default.TestExtension_chatincode_SoapExtensionService;
if ((this.IsLocalFileSystemWebService(this.Url) == true)) {
this.UseDefaultCredentials = true;
this.useDefaultCredentialsSetExplicitly = false;
}
else {
this.useDefaultCredentialsSetExplicitly = true;
}
}
public new string Url {
get {
return base.Url;
}
set {
if ((((this.IsLocalFileSystemWebService(base.Url) == true)
&& (this.useDefaultCredentialsSetExplicitly == false))
&& (this.IsLocalFileSystemWebService(value) == false))) {
base.UseDefaultCredentials = false;
}
base.Url = value;
}
}
public new bool UseDefaultCredentials {
get {
return base.UseDefaultCredentials;
}
set {
base.UseDefaultCredentials = value;
this.useDefaultCredentialsSetExplicitly = true;
}
}
///<remarks/>
public event LoginCompletedEventHandler LoginCompleted;
///<remarks/>
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/Login", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
[CryptExtension(Encrypt=EncryptModes.Request,Decrypt=DecryptModes.Response)]
public bool Login(string username, string password) {
object[] results = this.Invoke("Login", new object[] {
username,
password});
return ((bool)(results[0]));
}
///<remarks/>
public void LoginAsync(string username, string password) {
this.LoginAsync(username, password, null);
}
///<remarks/>
public void LoginAsync(string username, string password, object userState) {
if ((this.LoginOperationCompleted == null)) {
this.LoginOperationCompleted = new System.Threading.SendOrPostCallback(this.OnLoginOperationCompleted);
}
this.InvokeAsync("Login", new object[] {
username,
password}, this.LoginOperationCompleted, userState);
}
private void OnLoginOperationCompleted(object arg) {
if ((this.LoginCompleted != null)) {
System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
this.LoginCompleted(this, new LoginCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
}
}
///<remarks/>
public new void CancelAsync(object userState) {
base.CancelAsync(userState);
}
private bool IsLocalFileSystemWebService(string url) {
if (((url == null)
|| (url == string.Empty))) {
return false;
}
System.Uri wsUri = new System.Uri(url);
if (((wsUri.Port >= 1024)
&& (string.Compare(wsUri.Host, "localHost", System.StringComparison.OrdinalIgnoreCase) == 0))) {
return true;
}
return false;
}
}
///<remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.1")]
public delegate void LoginCompletedEventHandler(object sender, LoginCompletedEventArgs e);
///<remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.1")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class LoginCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
private object[] results;
internal LoginCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
base(exception, cancelled, userState) {
this.results = results;
}
///<remarks/>
public bool Result {
get {
this.RaiseExceptionIfNecessary();
return ((bool)(this.results[0]));
}
}
}
}
@灰灰快跑: 看到没,从System.Web.Services.Protocols.SoapHttpClientProtocol这个继承过来的才是WebService客户端调用的代理类
@灰灰快跑: Oh, My God! 你要使用SoapExtension这个过时技术,又,你添加的是WCF的客户端啊,这两种技术根本是不相容的呀。有谁告诉你可以这样用的!要使用SoapExtension, 添加服务引用后,
再点一下高级(V)... 这个按钮,
选择一下添加Web引用(W)...
右击添加Web Services引用 指定Web ServicesURL,输入一个调用这个服务的名称,最后确实就就行了;
在你的程序里就可以调用了;
或引用wsdl文件 生成一个代理类;添加引用这个类;
我摘掉怎么引用webservice,但是不知道客户端怎么调用SOAP扩展
@灰灰快跑: webserivces 是你自己写的还是别人给你调用 的;自己的和类引用一下;别人给你的也是一样;实例化一个;调用其你要用的方法就行了
@058674: 是这样的,我做毕设用,客户端服务器端都是我写的,客户端调用Webservice;在传输过程中在SOAP扩展序列化反序列化的时候进行加密解密等处理。如果是B/S的话,配置一下<soapExtentionTypes>节点就可以了,可是我现在是C/S的,客户端是窗体应用程序,配置<system.web><soapExtentionTypes>节点不起作用。SOAP扩展类我已经写好了,其中也包括加密解密代码,现在就是不知道客户端怎么做才能进行SOAP扩展
@灰灰快跑 你好。我想咨询你几个问题。我的qq 是 516963056。可以联系你吗?