zoukankan      html  css  js  c++  java
  • 稳扎稳打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
    {
        
    /// <summary>
        
    /// 返回指定的 User 对象(用于演示传输信息的加密/解密)
        
    /// </summary>
        
    /// <param name="name"></param>
        
    /// <returns></returns>

        [OperationContract]
        
    public User GetUserByCryptography(string name)
        
    {
            
    return new User { Name = Decrypt(name), DayOfBirth = new DateTime(1980214) };
        }


        
    /// <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
    [源码下载]
  • 相关阅读:
    POJ
    POJ
    POJ1753 Flip Game(位运算+暴力枚举)
    20160326 javaweb 请求转发和请求包含
    将博客搬至CSDN
    javaweb 中的乱码问题
    20160324 javaweb 之request
    20160322 javaweb 学习笔记--response验证码实现
    20160322 javaweb 学习笔记--response 重定向
    深入分析 Java 中的中文编码问题 (文章来自网络)
  • 原文地址:https://www.cnblogs.com/webabcd/p/1355036.html
Copyright © 2011-2022 走看看