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

2016-08-20 11:01:06来源:http://webabcd.blog.51cto.com/1787395/343130作者:webabcd人点击


[索引页][源码下载]
稳扎稳打Silverlight(22) - 2.0通信之调用WCF服务, 对传输信息做加密作者:webabcd介绍Silverlight 2.0调用 WCF 服务,对客户端与服务端传输的消息做加密 在 Visual Studio 2008 中使用"添加服务引用"会自动生成代理类。只支持BasicHttpBinding在线DEMOhttp://webabcd.blog.51cto.com/1787395/342779示例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(1980, 2, 14) }; } }

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 { /// <summary> /// 返回指定的 User 对象(用于演示传输信息的加密/解密) /// </summary> /// <param name="name"></param> /// <returns></returns> [OperationContract] public User GetUserByCryptography(string name) { return new User { Name = Decrypt(name), DayOfBirth = new DateTime(1980, 2, 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, 0, 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, 0, data.Length); encryptor.Close(); // 将加密后所得到的流转换成字节数组,再用Base64编码将其转换为字符串 string encryptedString = Convert.ToBase64String(encryptStream.ToArray()); return encryptedString; } } }


OK[源码下载]

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台