[转]如何借助 TLS/SSL 确保套接字连接的安全(使用 C#/VB/C++ 和 XAML 的 Windows 应用商店应用)
本文转自:http://msdn.microsoft.com/zh-cn/library/windows/apps/jj150597.aspx
本主题将展示在使用 StreamSocket 功能时,如何使 Windows 应用商店应用可以保护 TLS/SSL 流套接字连接。
你需要了解的内容
技术
- Windows.Networking.Sockets
使用套接字和 WebSocket 启用网络通信。
先决条件
- 在本主题中,以下示例都来自 C# 和 C++。建议对套接字和 SSL/TLS 的使用有一个基本的了解。
SSL/TLS 连接概述
安全套接字层 (SSL) 和最新的传输层安全 (TLS) 都是旨在为网络通信提供身份验证和加密功能的加密协议。这些协议专门用于在发送和接收网络数据时防止发生窃听和篡改。 这些协议使用一种客户端-服务器模型进行协议交换。这些协议还会使用数字证书和证书颁发机构来验证服务器是否与其自称的身份相符。TLS 协议记录在 IETF RFC 5246 中。 早期的 SSL 协议由 Netscape Communications 记录。 SSL 通常用于指这两种协议。
StreamSocket 对象可以配置用于在客户端和服务器之间使用 SSL/TLS 进行通信。对 SSL/TLS 的支持仅限于在 SSL/TLS 协商中将 StreamSocket 对象用作客户端。当系统接受一个连接以在被创建的 StreamSocket 上启用 SSL/TLS 时,由于作为服务器的 SSL/TLS 协商没有为 StreamSocket 实现,所以StreamSocketListener 现在不能使用 SSL/TLS 用于被创建的 StreamSocket。 SSL/TLS 的客户端支持不包括使用客户端证书的功能。
有以下两种方法可以借助 SSL/TLS 确保 StreamSocket 连接的安全:
- ConnectAsync - 建立到网络服务的初始连接并立即协商对所有通信使用 SSL/TLS。
- UpgradeToSslAsync - 先不加密连接到网络服务。应用可以发送或接收数据。然后升级连接,对此后所有通信使用 SSL/TLS。
使用 ConnectAsync
建立与网络服务的初始连接并立即协商对所有通信使用 SSL/TLS。有两种 ConnectAsync 方法支持传递protectionLevel 参数:
- ConnectAsync(EndpointPair, SocketProtectionLevel) - 在 StreamSocket 对象上启动异步操作以连接到EndpointPair 对象和 SocketProtectionLevel 所指定的远程网络目标。
- ConnectAsync(HostName, String, SocketProtectionLevel) - 在 StreamSocket 对象上启动异步操作以连接到由远程主机名、远程服务名和 SocketProtectionLevel 所指定的远程目标。
如果 protectionLevel 参数被设置为 Windows.Networking.Sockets.SocketProtectionLevel.Ssl,当调用上述任一ConnectAsync 方法时,StreamSocket 必须使用 SSL/TLS 用于加密。此值需要加密而且绝不允许使用 NULL 密码。
一般来说,使用这些 ConnectAsync 方法的顺序都是相同的。
- 创建一个 StreamSocket。
- 如果需要在套接字上使用高级选项,请使用 StreamSocket.Control 属性获取与 StreamSocket 对象 相关联的StreamSocketControl 实例。 针对 StreamSocketControl 设置一个属性。
- 调用上述 ConnectAsync 方法之一以启动连接到远程目标的操作,并立即协商使用 SSL/TLS。
以下示例将会创建 StreamSocket,并尝试建立与网络服务的连接并立即协商使用 SSL/TLS。如果协商成功,则在客户端和网络服务器之间使用 StreamSocket 的所有网络通信都将被加密。
using Windows.Networking;
using Windows.Networking.Sockets; // Define some variables and set values
StreamSocket clientSocket = new StreamSocket(); HostName serverHost = new HostName("www.contoso.com");
string serverServiceName = "https"; // For simplicity, the sample omits implementation of the
// NotifyUser method used to display status and error messages // Try to connect to contoso using HTTPS (port 443)
try { // Call ConnectAsync method with SSL
await clientSocket.ConnectAsync(serverHost, serverServiceName, SocketProtectionLevel.Ssl); NotifyUser("Connected");
}
catch (Exception exception) {
// If this is an unknown status it means that the error is fatal and retry will likely fail.
if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown) {
throw;
} NotifyUser("Connect failed with error: " + exception.Message);
// Could retry the connection, but for this simple example
// just close the socket. clientSocket.Dispose();
clientSocket = null;
} // Add code to send and receive data using the clientSocket
// and then close the clientSocket
使用 UpgradeToSslAsync
先不加密建立与网络服务的初始连接。应用可以发送或接收数据。然后升级连接,对此后所有通信使用 SSL/TLS。使用如下方法:
- UpgradeToSslAsync - 启动一个异步操作以升级到在 StreamSocket 对象上使用 SSL。
UpgradeToSslAsync 方法有两个参数。protectionLevel 参数表示所需的保护级别。validationHostName 参数是在升级到 SSL 时用于进行验证的远程网络目标的主机名。 通常情况下,validationHostName 将是应用最初建立连接时所使用的相同主机名。如果 protectionLevel 参数被设置为 Windows.System.Socket.SocketProtectionLevel.Ssl,当调用上述任一 UpgradeToSslAsync 方法时,StreamSocket 必须使用 SSL/TLS 用于加密。此值需要加密而且绝不允许使用 NULL 密码。
一般来说,使用 UpgradeToSslAsync 方法的顺序都是:
- 创建一个 StreamSocket。
- 如果需要在套接字上使用高级选项,请使用 StreamSocket.Control 属性获取与 StreamSocket 对象 相关联的StreamSocketControl 实例。 针对 StreamSocketControl 设置一个属性。
- 如果任何数据需要以不加密的形式进行发送和接收,则立即发送。
- 调用 UpgradeToSslAsync 方法以启动将连接升级为使用 SSL/TLS。
以下示例将会创建 StreamSocket,并尝试建立与网络服务的连接、发送一些初始数据,然后协商使用 SSL/TLS。如果协商成功,则在客户端和网络服务器之间使用 StreamSocket 的所有网络通信都将被加密。
using Windows.Networking;
using Windows.Networking.Sockets;
using Windows.Storage.Streams; // Define some variables and set values
StreamSocket clientSocket = new StreamSocket(); HostName serverHost = new HostName("www.contoso.com");
string serverServiceName = "http"; // For simplicity, the sample omits implementation of the
// NotifyUser method used to display status and error messages // Try to connect to contoso using HTTP (port 80)
try {
// Call ConnectAsync method with a plain socket
await clientSocket.ConnectAsync(serverHost, serverServiceName, SocketProtectionLevel.PlainSocket); NotifyUser("Connected"); }
catch (Exception exception) {
// If this is an unknown status it means that the error is fatal and retry will likely fail.
if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown) {
throw;
} NotifyUser("Connect failed with error: " + exception.Message, NotifyType.ErrorMessage);
// Could retry the connection, but for this simple example
// just close the socket. clientSocket.Dispose();
clientSocket = null;
return;
} // Now try to sent some data
DataWriter writer = new DataWriter(clientSocket.OutputStream);
string hello = "Hello World ☺ ";
Int32 len = (int) writer.MeasureString(hello); // Gets the UTF-8 string length.
writer.WriteInt32(len);
writer.WriteString(hello);
NotifyUser("Client: sending hello"); try {
// Call StoreAsync method to store the hello message
await writer.StoreAsync(); NotifyUser("Client: sent data"); writer.DetachStream(); // Detach stream, if not, DataWriter destructor will close it.
}
catch (Exception exception) {
NotifyUser("Store failed with error: " + exception.Message);
// Could retry the store, but for this simple example
// just close the socket. clientSocket.Dispose();
clientSocket = null;
return;
} // Now upgrade the client to use SSL
try {
// Try to upgrade to SSL
await clientSocket.UpgradeToSslAsync(SocketProtectionLevel.Ssl, serverHost); NotifyUser("Client: upgrade to SSL completed"); // Add code to send and receive data
// The close clientSocket when done
}
catch (Exception exception) {
// If this is an unknown status it means that the error is fatal and retry will likely fail.
if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown) {
throw;
} NotifyUser("Upgrade to SSL failed with error: " + exception.Message); clientSocket.Dispose();
clientSocket = null;
return;
}
备注
SocketProtectionLevel 枚举 有三个可能的值:
- PlainSocket - 一个未加密的纯套接字。
- Ssl - 一个必须使用 SSL/TLS 进行加密的套接字。此值需要加密而且绝不允许使用 NULL 密码。
- SslAllowNullEncryption - 一个首选使用 SSL/TLS 进行加密的套接字。该值首选使用完全加密,但允许基于服务器的配置使用 NULL 密码(即不加密)。
通常不使用 SslAllowNullEncryption 值,因为它允许使用 NULL 密码,这就意味着不加密,所以网络通信可能也不加密。SslAllowNullEncryption 值允许 SSL/TLS 协商,以根据服务器数字证书和证书颁发机构对服务器进行验证。
如果使用 SslAllowNullEncryption 值,那么实际上使用 ConnectAsync 或 UpgradeToSslAsync 协商得到的 SSL 强度可通过获取 StreamSocketinformation.ProtectionLevel 属性来确定。
相关主题
- 其他
- 使用套接字进行连接
- 使用套接字进行连接(使用 JavaScript 和 HTML 的 Windows 应用商店应用)
- 如何借助 TLS/SSL 确保套接字连接的安全(使用 JavaScript 和 HTML 的 Windows 应用商店应用)
- 如何使用高级套接字控件
- 快速入门:使用流套接字进行连接
- 参考
- SocketProtectionLevel
- StreamSocket
- StreamSocket.ConnectAsync
- StreamSocket.UpgradeToSslAsync
- StreamSocketinformation.ProtectionLevel
- Windows.Networking.Sockets
[转]如何借助 TLS/SSL 确保套接字连接的安全(使用 C#/VB/C++ 和 XAML 的 Windows 应用商店应用)的更多相关文章
- fsockopen — 打开一个网络连接或者一个Unix套接字连接
fsockopen (PHP 4, PHP 5, PHP 7) 说明 resource fsockopen ( string $hostname [, int $port = -1 [, int &a ...
- Linux/UNIX套接字连接
套接字连接 套接字是一种通信机子.凭借这样的机制.客户/server系统的开发工作既能够在本地单机上进行.也能够夸网络进行. 套接字的创建和使用与管道是有差别的.由于套接字明白地将客户和server区 ...
- WCF 套接字连接已中止。这可能是由于处理消息时出错或远程主机超过接收超时或者潜在的网络资源问题导致的
一个项目需要用到推送的功能,就是服务器主动推送数据给多台客户机.于是采用了WCF的双工通讯netTcpBinding 写好的项目,在本机测试都没有问题. 如果放在局域网内测试,问题出来了:先是安全性问 ...
- 解决VMware虚拟机报错“无法连接MKS:套接字连接尝试次数太多,正在放弃”
1.错误描述 在VMware中打开虚拟机时报错: "无法连接MKS:套接字连接尝试次数太多,正在放弃" 物理机操作系统: Windows 7 虚拟机操作系统: Kali Linux ...
- Linux:【解决】无法连接 MKS:套接字连接尝试次数太多正在放弃
[解决]无法连接 MKS:套接字连接尝试次数太多正在放弃 操作: 我的电脑 -> 右键 -> 管理 -> 服务和应用程序 -> 服务: 开启下面的服务: 服务启动成功后,重 ...
- PHP Socket(套接字连接)扩展简介和使用方法
PHP socket扩展是基于流行的BSD sockets,实现了和socket通讯功能的底层接口,它可以和客户端一样当做一个socket服务器. 使用这些函数时请注意,虽然他们中有很多和C函数同名的 ...
- VMware Workstation “无法连接 MKS: 套接字连接尝试次数太多;正在放弃。” 解决方法【转】
今天和往常一样打开电脑,打开VMware Workstation,打开其中的一台虚拟机,以前都是这么打开没有问题,今天打开虚拟机突然提示“无法连接 MKS: 套接字连接尝试次数太多:正在放弃.”. 经 ...
- Vmware Pro 14报错:无法连接 MKS: 套接字连接尝试次数太多;正在放弃。
软件环境: 虚拟机软件:VMware Pro 14 母机操作系统:win7 客户机操作系统:CentOS 7 问题详情: 报错:无法连接 MKS: 套接字连接尝试次数太多:正在放弃. ...
- VMware无法连接MKS:套接字连接尝试次数太多解决
粘贴自:https://jingyan.baidu.com/article/425e69e61eb578be15fc16ae.html VMware在开启虚拟机的时候,突然弹出[无法连接MKS:套接字 ...
随机推荐
- RequestMapping注解_修饰类
[使用RequestMapping映射请求] 1.Spring MVC使用 @RequestMapping 注解为控制器指定可以处理哪些URL请求. 2.在控制器的类定义及方法定义处都可以标注. @R ...
- UVA 12697 Minimal Subarray Length
Minimal Subarray Length Time Limit: 3000ms Memory Limit: 131072KB This problem will be judged on UVA ...
- hrbust oj 1536 Leonardo's Notebook 置换群问题
题目大意: 给出一个A~Z的置换G,问能否找到一个A~Z的置换G' 能够用来表示为 G = G'*G' 由定理: 任意一个长为 L 的置换的k次幂,都会把自己的每一个循环节分裂成gcd(L, K)份, ...
- noip模拟赛 立方数2
题目描述LYK定义了一个数叫“立方数”,若一个数可以被写作是一个正整数的3次方,则这个数就是立方数,例如1,8,27就是最小的3个立方数.LYK还定义了一个数叫“立方差数”,若一个数可以被写作是两个立 ...
- lombok中的@ToString注解作用
Lombok是一个很好的工具,节省了很多重写方法,而@ToString就是节省了ToString方法,lombok中@ToString就是节省了我们在模型中的冗余代码下面就来举个例子 import j ...
- - > 动规讲解基础讲解七——最长单增子序列
(LIS Longest Increasing Subsequence)给定一个数列,从中删掉任意若干项剩余的序列叫做它的一个子序列,求它的最长的子序列,满足子序列中的元素是单调递增的. 例如给定序列 ...
- SiteMesh2-sitemesh.xml的其它映射器的用法
在sitemesh.xml中做常用的三个映射器,总结如下: 映射器元素的顺序确定优先级.良好的应用程序应使用以下顺序, Parameter query = ParameterDecoratorMapp ...
- DICOM:dcm4che工具包怎样压缩dcm文件探讨(续篇)
背景 前段时间博文DICOM:dcm4che工具包怎样压缩dcm文件探讨(前篇)提到了一个问题:"利用dcm4che工具包中的dcm2dcm来进行dcm文件的压缩和加压缩.即改变dcm文件里 ...
- 【CV论文阅读】Two stream convolutional Networks for action recognition in Vedios
论文的三个贡献 (1)提出了two-stream结构的CNN,由空间和时间两个维度的网络组成. (2)使用多帧的密集光流场作为训练输入,可以提取动作的信息. (3)利用了多任务训练的方法把两个数据集联 ...
- [JavaEE] Implement a test for REST endpoint
1. We have the BookEndpoint.java: package com.pluralsight.bookstore.rest; import com.pluralsight.boo ...