[转]如何借助 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:套接字 ...
随机推荐
- cmake 学习笔记(一) buildsystem
参见网址: http://www.cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html Introduction 基于CMake的构建 ...
- 洛谷 2173 BZOJ 2816 [ZJOI2012]网络
[题解] 明显的LCT模板题,c种颜色就开c棵LCT好了.. #include<cstdio> #include<algorithm> #define N 100010 #de ...
- 1031. Hello World for U
Given any string of N (>=5) characters, you are asked to form the characters into the shape of U. ...
- __setitem__() __getitem__() __delitem__()
#item系列 和对象使用[]访问值有联系 #obj={'k':'v'} #print(obj) #print(obj['k']) class B: def __getitem__(self, ite ...
- java nio--采用Selector实现Socket通信
server: /** * 选择器服务端 * Created by ascend on 2017/6/9 9:30. */ public class SelectorServer { // publi ...
- Docker学习总结(18)——阿里超大规模Docker化之路
12月6-7日,由阿里巴巴集团.阿里巴巴技术发展部.阿里云云栖社区联合主办,以"2016双11技术创新"为主题的阿里巴巴技术论坛上,阿里巴巴研究员林昊分享了阿里超大规模Docker ...
- noip模拟赛 三角形
[问题描述] 平面上有N条直线,用方程Aix + Biy +Ci =0表示.这些直线没有三线共点的.现在要你计算出用这些直线可以构造出多少三角形? 输入: 第1行:一个整数N(1 ≤ N≤ 30000 ...
- hdu_1205_吃糖果_201404021440
吃糖果 Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Total Submis ...
- MYSQL常用的字符串函数
#字符串函数 #返回字符串的字符数量,对于此例而言,结果为5SELECT CHAR_LENGTH('计算机编程'); #合并字符串,对于此例而言,结果为‘我喜欢计算机’SELECT CONCAT('我 ...
- zoj 月赛
Wumpus Time Limit: 2 Seconds Memory Limit: 65536 KB One day Leon finds a very classic game call ...