微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

稳扎稳打Silverlight(22) - 2.0通信之调用WCF服务, 对传输信息做加密

[索引页]
[源码下载]


稳扎稳打Silverlight(22) - 2.0通信之调用WCF服务,对传输信息做加密


作者: webabcd


介绍
Silverlight 2.0 调用 WCF 服务,对客户端与服务端传输的消息做加密    
    在 Visual Studio 2008 中使用"添加服务引用"会自动生成代理类。只支持BasicHttpBinding


在线DEMO
http://www.cnblogs.com/webabcd/archive/2008/10/09/1307486.html


示例
clientaccesspolicy.xml

<? xml version="1.0" encoding="utf-8"  ?>

< access-policy >

    
< cross-domain-access >

        
< policy >

            
< allow-from  http-request-headers ="*" >

                
< domain  uri ="*"   />

            
</ allow-from >

            
< grant-to >

                
< resource  path ="/"  include-subpaths ="true"   />

            
</ grant-to >

        
</ policy >

    
</ cross-domain-access >

</ access-policy >

<!--

System.Net 命名空间 和 System.Net.sockets 命名空间的跨域调用,需要在目标域的根目录下配置策略文件

Image 控件 和 MediaElement 控件所访问的跨域地址,不受策略文件的限制

HTTP 调用 仅支持 GET 和 POST ,只有 200(确定) 和 404(未找到) 状态代码可用

同域:同一子域、协议和端口。不符合以上任一条件则为跨域

Silverlight 与 HTTP/HTTPS 的所有通信均为异步


关于策略文件详见文档

-->


1、调用 WCF 服务
WCFService.cs(WCF 服务)

using  System;

using  System.Linq;

using  System.Runtime.Serialization;

using  System.ServiceModel;

using  System.ServiceModel.Activation;

using  System.Collections.Generic;

using  System.Text;


using  System.Security.Cryptography;

using  System.IO;


/// <summary>

/// 提供 WCF 服务的类

/// </summary>

[ServiceContract]

[AspNetCompatibilityRequirements(RequirementsMode 
=  AspNetCompatibilityRequirementsMode.Allowed)]

public   class  WCFService

{

    
/// <summary>

    
/// 返回指定的 User 对象(用于演示 Silverlight 调用 WCF 服务)

    
/// </summary>

    
/// <param name="name">名字</param>

    
/// <returns></returns>

    [OperationContract]

    
public User GetUser(string name)

    
{

        
return new User { Name = name, DayOfBirth = new DateTime(1980214) };

    }

}


WCF.xaml

< UserControl  x:Class ="Silverlight20.Communication.WCF"

    xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  

    xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml" >

    
< StackPanel  HorizontalAlignment ="Left"  Margin ="5" >

    

        
< TextBlock  x:Name ="lblMsg"   />

    

    
</ StackPanel >

</ UserControl >


WCF.xaml.cs

using  System;

using  System.Collections.Generic;

using  System.Linq;

using  System.Net;

using  System.Windows;

using  System.Windows.Controls;

using  System.Windows.Documents;

using  System.Windows.Input;

using  System.Windows.Media;

using  System.Windows.Media.Animation;

using  System.Windows.Shapes;


using  Silverlight20.WCFServiceReference;

using  System.Threading;

using  System.ServiceModel;


namespace  Silverlight20.Communication

{

    
public partial class WCF : UserControl

    
{

        SynchronizationContext _syncContext;


        
/// <summary>

        
/// 演示 Silverlight 调用 WCF 服务

        
/// </summary>

        public WCF()

        
{

            InitializeComponent();


            
// 代理的配置信息在配置文件中,UI线程上的异步调用

            Demo();


            
// 代理的配置信息在程序中指定,UI线程上的异步调用

            Demo2();


            
// 后台线程(非UI线程)上的异步调用

            Demo3();

        }


        
void Demo()

        
{

            
/*             

             * 服务名Client - 系统自动生成的代理类

             *     方法名Completed - 调用指定的方法完成后所触发的事件

             *     方法名Async(参数1, 参数2 

, object 用户标识) - 异步调用指定的方法

             *     Abort() - 取消调用

             
*/


            WCFServiceClient client 
= new WCFServiceClient();

            client.GetUserCompleted 
+= new EventHandler<GetUserCompletedEventArgs>(client_GetUserCompleted);

            client.GetUserAsync(
"webabcd");

        }


        
void Demo2()

        
{

            
/*

             * 服务名Client - 其构造函数可以动态地指定代理的配置信息(Silverlight 2.0 调用 WCF 只支持 BasicHttpBinding)

             
*/


            WCFServiceClient client 
= new WCFServiceClient(new BasicHttpBinding(), new EndpointAddress("http://localhost:3036/WCFService.svc"));

            client.GetUserCompleted 
+= new EventHandler<GetUserCompletedEventArgs>(client_GetUserCompleted);

            client.GetUserAsync(
"webabcd2");

        }


        
void client_GetUserCompleted(object sender, GetUserCompletedEventArgs e)

        
{

            
/*

             * 方法名CompletedEventArgs.Error - 该异步操作期间是否发生了错误

             * 方法名CompletedEventArgs.Result - 异步操作返回的结果。本例为 User 类型

             * 方法名CompletedEventArgs.UserState - 用户标识

             
*/


            
if (e.Error != null)

            
{

                lblMsg.Text 
+= e.Error.ToString() + "/r/n";

                
return;

            }


            
if (e.Cancelled != true)

            
{

                OutputResult(e.Result);

            }

        }


        
void Demo3()

        
{

            
// UI 线程

            _syncContext = SynchronizationContext.Current;


            
/*

             * ChannelFactory<T>.CreateChannel() - 创建 T 类型的信道

             * 服务名.Begin方法名() - 后台线程上异步调用指定方法(最后一个参数为 代理对象)

             
*/


            WCFService client 
= new ChannelFactory<WCFService>(new BasicHttpBinding(), new EndpointAddress("http://localhost:3036/WCFService.svc")).CreateChannel();

            client.BeginGetUser(
"webabcd3"new AsyncCallback(ResponseCallback), client);

        }


        
private void ResponseCallback(IAsyncResult result)

        
{

            WCFService client 
= result.AsyncState as WCFService;


            
// 服务名.End方法名() - 获取后台线程(非UI线程)上异步调用的结果

            User user = client.EndGetUser(result);


            
// 调用 UI 线程

            _syncContext.Post(GetResponse, user);

        }


        
private void GetResponse(object state)

        
{

            OutputResult(state 
as User);

        }



        
/// <summary>

        
/// 输出异步调用 WCF 服务的方法后返回的结果

        
/// </summary>

        
/// <param name="user"></param>

        void OutputResult(User user)

        
{

            lblMsg.Text 
+= string.Format("姓名:{0};生日:{1}/r/n",

                user.Name,

                user.DayOfBirth.ToString(
"yyyy-MM-dd"));

        }

    }

}


2、对客户端与服务端传输的消息做加密
WCFService.cs(WCF 服务)

using  System;

using  System.Linq;

using  System.Runtime.Serialization;

using  System.ServiceModel;

using  System.ServiceModel.Activation;

using  System.Collections.Generic;

using  System.Text;


using  System.Security.Cryptography;

using  System.IO;


/// <summary>

/// 提供 WCF 服务的类

/// </summary>

[ServiceContract]

[AspNetCompatibilityRequirements(RequirementsMode 
=  AspNetCompatibilityRequirementsMode.Allowed)]

public   class  WCFService

@H_502_2044@

{

    
/// <summary>

    
/// 返回指定的 User 对象(用于演示传输信息的加密/解密)

    
/// </summary>

    
/// <param name="name"></param>

    
/// <returns></returns>

    [OperationContract]

    
public User GetUserByCryptography(string name)

    
{

        
return new User { Name = Decrypt(name), 14) };

    }


    
/// <summary>

    
/// 解密数据

    
/// </summary>

    
/// <param name="input">加密后的字符串</param>

    
/// <returns>加密前的字符串</returns>

    public string Decrypt(string input)

    
{

        
// 盐值(与加密时设置的值一致)

        string saltValue = "saltValue";

        
// 密码值(与加密时设置的值一致)

        string pwdValue = "pwdValue";


        
byte[] encryptBytes = Convert.FromBase64String(input);

        
byte[] salt = Encoding.UTF8.GetBytes(saltValue);


        AesManaged aes 
= new AesManaged();


        Rfc2898DeriveBytes rfc 
= new Rfc2898DeriveBytes(pwdValue, salt);


        aes.BlockSize 
= aes.LegalBlockSizes[0].MaxSize;

        aes.KeySize 
= aes.LegalKeySizes[0].MaxSize;

        aes.Key 
= rfc.GetBytes(aes.KeySize / 8);

        aes.IV 
= rfc.GetBytes(aes.BlockSize / 8);


        
// 用当前的 Key 属性和初始化向量 IV 创建对称解密器对象

        ICryptoTransform decryptTransform = aes.CreateDecryptor();


        
// 解密后的输出

        MemoryStream decryptStream = new MemoryStream();


        
// 将解密后的目标流(decryptStream)与解密转换(decryptTransform)相连接

        CryptoStream decryptor = new CryptoStream(decryptStream, decryptTransform, CryptoStreamMode.Write);


        
// 将一个字节序列写入当前 CryptoStream (完成解密的过程)

        decryptor.Write(encryptBytes, 0, encryptBytes.Length);

        decryptor.Close();


        
// 将解密后所得到的流转换为字符串

        byte[] decryptBytes = decryptStream.ToArray();

        
string decryptedString = UTF8Encoding.UTF8.GetString(decryptBytes, decryptBytes.Length);


        
return decryptedString;

    }

}


Cryptography.xaml

< UserControl  x:Class ="Silverlight20.Communication.Cryptography"

    xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  

    xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml" >

    
< StackPanel  HorizontalAlignment ="Left"  Margin ="5" >

    

        
< TextBlock  x:Name ="lblMsg"   />

    

    
</ StackPanel >

</ UserControl >


Cryptography.xaml.cs

using  System;

using  System.Collections.Generic;

using  System.Linq;

using  System.Net;

using  System.Windows;

using  System.Windows.Controls;

using  System.Windows.Documents;

using  System.Windows.Input;

using  System.Windows.Media;

using  System.Windows.Media.Animation;

using  System.Windows.Shapes;


using  Silverlight20.WCFServiceReference;

using  System.Text;

using  System.Security.Cryptography;

using  System.IO;


namespace  Silverlight20.Communication

{

    
public partial class Cryptography : UserControl

    
{

        
public Cryptography()

        
{

            InitializeComponent();


            Demo();

        }


        
void Demo()

        
{

            WCFServiceClient client 
= new WCFServiceClient();


            client.GetUserByCryptographyCompleted
+=new EventHandler<GetUserByCryptographyCompletedEventArgs>(client_GetUserByCryptographyCompleted);

            client.GetUserByCryptographyAsync(Encrypt(
"webabcd"));

        }


        
void client_GetUserByCryptographyCompleted(object sender, GetUserByCryptographyCompletedEventArgs e)

        
{

            
if (e.Error != null)

            
{

                lblMsg.Text 
+= e.Error.ToString() + "/r/n";

                
return;

            }


            
if (e.Cancelled != true)

            
{

                lblMsg.Text 
+= string.Format("姓名:{0};生日:{1}/r/n",

                    e.Result.Name,

                    e.Result.DayOfBirth.ToString(
"yyyy-MM-dd"));

            }

        }


        
/// <summary>

        
/// 加密数据

        
/// </summary>

        
/// <param name="input">加密前的字符串</param>

        
/// <returns>加密后的字符串</returns>

        private string Encrypt(string input)

        
{

            
// 盐值

            string saltValue = "saltValue";

            
// 密码

            string pwdValue = "pwdValue";


            
byte[] data = UTF8Encoding.UTF8.GetBytes(input);

            
byte[] salt = UTF8Encoding.UTF8.GetBytes(saltValue);


            
// AesManaged - 高级加密标准(AES) 对称算法的管理类

            AesManaged aes = new AesManaged();


            
// Rfc2898DeriveBytes - 通过使用基于 HMACSHA1 的伪随机生成器,实现基于密码的密钥派生功能 (PBKDF2 - 一种基于密码的密钥派生函数)

            
// 通过 密码 和 salt 派生密钥

            Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(pwdValue, salt);


            
/*

             * AesManaged.BlockSize - 加密操作的块大小(单位:bit)

             * AesManaged.LegalBlockSizes - 对称算法支持的块大小(单位:bit)

             * AesManaged.KeySize - 对称算法的密钥大小(单位:bit)

             * AesManaged.LegalKeySizes - 对称算法支持的密钥大小(单位:bit)

             * AesManaged.Key - 对称算法的密钥

             * AesManaged.IV - 对称算法的密钥大小

             * Rfc2898DeriveBytes.GetBytes(int 需要生成的伪随机密钥字节数) - 生成密钥

             
*/


            aes.BlockSize 
= aes.LegalBlockSizes[0].MaxSize;

            aes.KeySize 
= aes.LegalKeySizes[0].MaxSize;

            aes.Key 
= rfc.GetBytes(aes.KeySize / 8);

            aes.IV 
= rfc.GetBytes(aes.BlockSize / 8);


            
// 用当前的 Key 属性和初始化向量 IV 创建对称加密器对象

            ICryptoTransform encryptTransform = aes.CreateEncryptor();


            
// 加密后的输出

            MemoryStream encryptStream = new MemoryStream();


            
// 将加密后的目标流(encryptStream)与加密转换(encryptTransform)相连接

            CryptoStream encryptor = new CryptoStream(encryptStream, encryptTransform, CryptoStreamMode.Write);


            
// 将一个字节序列写入当前 CryptoStream (完成加密的过程)

            encryptor.Write(data, data.Length);

            encryptor.Close();


            
// 将加密后所得到的流转换成字节数组,再用Base64编码将其转换为字符串

            string encryptedString = Convert.ToBase64String(encryptStream.ToArray());


            
return encryptedString;

        }
        

    }

}



OK
[源码下载]

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐