日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

用TLS实现安全TCP传输及配置和访问https的web服务(转)

發(fā)布時(shí)間:2025/3/20 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 用TLS实现安全TCP传输及配置和访问https的web服务(转) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

tls相關(guān)

大致原理

為了讓兩個(gè)之間實(shí)現(xiàn)安全傳輸,(我們把服務(wù)端統(tǒng)一叫做TcpServer,客戶端統(tǒng)一叫做TcpClient),TcpServerlisten完了accept之后要用一個(gè)證書來(lái)聲明自己是誰(shuí),而TcpClientconnect之后要問(wèn)TcpServer是否具有自己想要的一個(gè)證書(確認(rèn)服務(wù)端身份),如果是自己指定的那個(gè)證書,就說(shuō)明是自己要連接的那個(gè)TcpServer,這時(shí)候連接就會(huì)建立成功,以后發(fā)給TcpServer的數(shù)據(jù),都會(huì)用TcpServer聲明的證書里面的公鑰來(lái)加密后再發(fā)送給TcpServerTcpServer會(huì)用自己機(jī)器里的私鑰對(duì)數(shù)據(jù)解密。

以上保證了TcpClient不會(huì)連接到非法的TcpServer,第三方截取TcpClient發(fā)送的數(shù)據(jù)也解不開(kāi)。

然后TcpServer也可以(可選)要求TcpClient必須提供證書,用以證明是傳入的TcpClient自己信任的TcpClientTcpClient會(huì)把證書(從某個(gè)CA申請(qǐng)的)進(jìn)行簽名后發(fā)送給TcpServerTcpServer會(huì)確認(rèn)TcpClient提供的證書發(fā)行者是否是自己信任的發(fā)行者(就是是否裝有這個(gè)發(fā)行者的根證書),如果信任就會(huì)建立連接成功。

以上保證了TcpServerTcpClient之間實(shí)現(xiàn)了雙向的身份驗(yàn)證,建立了信任連接。這時(shí)候TcpServerTcpClient會(huì)各自用一定的算法生成一個(gè)密鑰做為會(huì)話密鑰,并通知給對(duì)方,之后相互傳輸數(shù)據(jù)就用這個(gè)會(huì)話密鑰進(jìn)行對(duì)稱加密后傳給對(duì)方,這樣做是因?yàn)閷?duì)稱加密比非對(duì)稱加密性能要好一個(gè)數(shù)量級(jí)。(密鑰交換一般是服務(wù)端用一段隨機(jī)數(shù)傳給客戶端,客戶端用一段隨機(jī)數(shù)傳給服務(wù)端,這個(gè)傳輸是安全傳輸,然后雙方用兩個(gè)隨機(jī)數(shù)合并起來(lái)的一個(gè)數(shù)做為會(huì)話密鑰)

其中的用sha1做為消息完整性算法,3des做為消息機(jī)密性算法,rsa做為密鑰交換算法(在安全策略里打開(kāi)fips選項(xiàng) )。

證書相關(guān)操作

申請(qǐng)服務(wù)端證書

先找一臺(tái)機(jī)器裝上證書頒發(fā)服務(wù)(在添加/刪除程序-添加刪除windows組件里),然后再另一臺(tái)機(jī)器通過(guò)瀏覽器申請(qǐng)證書,該網(wǎng)址類似如下(其中ms-onlytiancai為證書服務(wù)器機(jī)器名):

http://ms-onlytiancai/certsrv/

選擇高級(jí)申請(qǐng)證書,如下圖,識(shí)別信息要填全,否則客戶端驗(yàn)證的時(shí)候會(huì)出現(xiàn)證書鏈(我測(cè)的時(shí)候確實(shí)如此,但證書鏈的概念是根CA和多級(jí)的中級(jí)CA之間信任關(guān)系的一個(gè)鏈,具體看相關(guān)鏈接)失敗。d

證書類型要選擇“服務(wù)器身份驗(yàn)證證書(有些CA可能沒(méi)有單獨(dú)的這樣的模板,那就選擇“計(jì)算機(jī)副本”證書,該證書可以用來(lái)驗(yàn)證服務(wù)器身份和客戶端身份)”,其它選項(xiàng)不要?jiǎng)?#xff0c;最后點(diǎn)申請(qǐng),然后再在CA服務(wù)器的【管理工具】-【證書頒發(fā)機(jī)構(gòu)】的“掛起的證書”里把剛申請(qǐng)的證書頒發(fā)一下,最后還在證書申請(qǐng)網(wǎng)頁(yè)上點(diǎn)“查看掛起的證書申請(qǐng)的狀態(tài)”,通過(guò)向?qū)?#xff0c;安裝證書,提示你是否信任該CA時(shí),點(diǎn)是,這時(shí)候會(huì)自動(dòng)把該證書安裝到“個(gè)人”區(qū)域,并把該CA證書安裝到“受信任的根證書頒發(fā)機(jī)構(gòu)”。這一步是必須的,這樣做服務(wù)端就會(huì)信任該CA發(fā)行的所有證書(如果這一步?jīng)]有安裝根證書,后面可以從控制臺(tái)里把CA證書單獨(dú)導(dǎo)入到本地計(jì)算機(jī)的受信任頒發(fā)機(jī)構(gòu)里,CA證書不是申請(qǐng)的,是直接在證書申請(qǐng)頁(yè)面的下方的鏈接下載的),后面申請(qǐng)客戶端證書的時(shí)候也從這個(gè)CA來(lái)申請(qǐng),服務(wù)端才會(huì)信任這個(gè)客戶端。

最后申請(qǐng)下來(lái)的證書,大致如上圖所示,必須是服務(wù)器身份認(rèn)證證書(至少證書目的里由“保證遠(yuǎn)程計(jì)算機(jī)身份”),而且必須得有一個(gè)該證書對(duì)應(yīng)的私鑰,這個(gè)私鑰應(yīng)該是在DPAPI(CAPI)存儲(chǔ)器里存著呢,按照上面的操作應(yīng)該會(huì)得到這樣的一個(gè)證書。用makecert -r -pe -n "CN=TestCert" -e 01/01/2036 -sr localMachine c:" TestCert.cer生成的證書不會(huì)有對(duì)應(yīng)的私鑰,這樣的證書是不能用的,到時(shí)候客戶端驗(yàn)證的時(shí)候會(huì)拋一個(gè)異常,提示你沒(méi)有私鑰(需要一個(gè)關(guān)聯(lián)私鑰的證書)。 查看本機(jī)已安裝的證書,在IE的選項(xiàng)-內(nèi)容-證書選項(xiàng)里(在控制臺(tái)里添加/刪除管理單元里添加“證書管理單元”也可以管理)。 ? 申請(qǐng)服務(wù)端證書,姓名字段一定要寫成服務(wù)器的名稱,netbios名或者dns名稱。

申請(qǐng)客戶端證書

過(guò)程和申請(qǐng)服務(wù)端證書一樣,只是證書類型選擇“客戶端身份驗(yàn)證證書”。

導(dǎo)出證書

在證書管理控制臺(tái)里把服務(wù)端證書和客戶端證書全部導(dǎo)出到本地,導(dǎo)出選項(xiàng)全部為默認(rèn)。

服務(wù)器為:C:"certs"huhao.pxe(帶私鑰)

客戶端為:C:"certs"client.cer

如果服務(wù)端為windows服務(wù),需要把服務(wù)端證書導(dǎo)入到本地計(jì)算機(jī)里,默認(rèn)服務(wù)器證書只安裝到了當(dāng)前用戶的個(gè)人區(qū)域,需要從當(dāng)前用戶的個(gè)人區(qū)域?qū)С鰜?lái),再導(dǎo)入到本地計(jì)算機(jī)的個(gè)人區(qū)域,導(dǎo)出的時(shí)候記著選上導(dǎo)出私鑰,否則導(dǎo)入到本地計(jì)算機(jī)里的證書就不會(huì)關(guān)聯(lián)私鑰了。

應(yīng)用相關(guān)

服務(wù)端代碼

??

?

類庫(kù)
using?System;
using?System.Net.Sockets;
using?System.Net;
using?System.Net.Security;
using?System.Security.Cryptography.X509Certificates;
using?System.Text;
using?System.Security.Authentication;
using?System.Threading;

class?TCPServer_SSL
{
????
private?TcpListener?_listener?=?null;
????
private?IPAddress?_address?=?IPAddress.Parse("127.0.0.1");
????
private?int?_port?=?55555;

????
CTORs#region?CTORs
????
public?TCPServer_SSL()
????
{
????}


????
public?TCPServer_SSL(string?address,?string?port)
????
{
????????_port?
=?Convert.ToInt32(port);
????????_address?
=?IPAddress.Parse(address);
????}

????
#endregion
?//?CTORs

????
Properties#region?Properties
????
public?IPAddress?Address
????
{
????????
get?{?return?_address;?}
????????
set?{?_address?=?value;?}
????}


????
public?int?Port
????
{
????????
get?{?return?_port;?}
????????
set?{?_port?=?value;?}
????}

????
#endregion


????
public?void?Listen()
????
{
????????
try
????????
{
????????????_listener?
=?new?TcpListener(_address,?_port);

????????????
//?Fire?up?the?server.
????????????_listener.Start();

????????????
//?Enter?the?listening?loop.
????????????while?(true)
????????????
{
????????????????Console.Write(
"Looking?for?someone?to?talk?to…?");

????????????????
//?Wait?for?connection.
????????????????TcpClient?newClient?=?_listener.AcceptTcpClient();
????????????????Console.WriteLine(
"Connected?to?new?client");

????????????????
//?Spin?a?thread?to?take?care?of?the?client.
????????????????ThreadPool.QueueUserWorkItem(new?WaitCallback(ProcessClient),
?????????????????????????????????????????newClient);
????????????}



????????}

????????
catch?(SocketException?e)
????????
{
????????????Console.WriteLine(
"SocketException:?{0}",?e);
????????}

????????
finally
????????
{
????????????
//?Shut?it?down.
????????????_listener.Stop();
????????}


????????Console.WriteLine(
"/nHit?any?key?(where?is?ANYKEY?)?to?continue…");
????????Console.Read();
????}


????
private?void?ProcessClient(object?client)
????
{
????????
using?(TcpClient?newClient?=?(TcpClient)client)
????????
{
????????????
//?Buffer?for?reading?data.
????????????byte[]?bytes?=?new?byte[1024];
????????????
string?clientData?=?null;

????????????
//第三個(gè)參數(shù)是驗(yàn)證客戶端證書的回調(diào),最后一個(gè)參數(shù)是用來(lái)指定多個(gè)證明自己的證書的回調(diào),這里為空
????????????
//前兩個(gè)參數(shù)分別是一個(gè)流和是否在關(guān)閉sslstrem關(guān)閉內(nèi)部流的選項(xiàng)
????????????using?(SslStream?sslStream?=?new?SslStream(newClient.GetStream(),?false,?ValidateClientCertificate,null))
????????????
{
????????????????
try
????????????????
{
????????????????????
//該方法的第一個(gè)參數(shù)是用于服務(wù)端身份驗(yàn)證的證書,第二個(gè)參數(shù)指定是否需要驗(yàn)證客戶端的身份
????????????????????
//第三個(gè)參數(shù)是指定安全傳輸?shù)膮f(xié)議,最后一個(gè)參數(shù)指定是否檢查吊銷證書
????????????????????sslStream.AuthenticateAsServer(GetServerCert("117f32ff000000000007"),?true,?SslProtocols.Tls,?false);
????????????????}

????????????????
catch?(Exception?ex)
????????????????
{
????????????????????Console.WriteLine(ex);
????????????????}


????????????????
//?Loop?to?receive?all?the?data?sent?by?the?client.
????????????????int?bytesRead?=?0;

????????????????
while?((bytesRead?=?sslStream.Read(bytes,?0,?bytes.Length))?!=?0)
????????????????
{
????????????????????
//?Translate?data?bytes?to?an?ASCII?string.
????????????????????clientData?=?Encoding.ASCII.GetString(bytes,?0,?bytesRead);
????????????????????Console.WriteLine(
"Client?says:?{0}",?clientData);

????????????????????
//?Thank?them?for?their?input.
????????????????????bytes?=?Encoding.ASCII.GetBytes("Thanks?call?again!");

????????????????????
//?Send?back?a?response.

????????????????????sslStream.Write(bytes,?
0,?bytes.Length);
????????????????}

????????????}

????????}

????}


????
public?static?bool?ValidateClientCertificate(object?sender,?X509Certificate?certificate,?X509Chain?chain,?SslPolicyErrors?sslPolicyErrors)
????
{
????????Console.WriteLine(
"ValidateClientCertificate-certificate.Subject:/r/n{0}",?certificate.Subject);
????????
if?(sslPolicyErrors?!=?SslPolicyErrors.None?&&?sslPolicyErrors?!=?SslPolicyErrors.RemoteCertificateChainErrors)
????????????
return?false;
????????
if?(sslPolicyErrors?!=?SslPolicyErrors.RemoteCertificateChainErrors)
????????
{
????????????
//不判斷吊銷證書
????????????foreach?(X509ChainStatus?s?in?chain.ChainStatus)
????????????
{
????????????????Console.WriteLine(
"ValidateClientCertificate-chain.ChainStatus:/r/n{0}-{1}",?s.Status,?s.StatusInformation);
????????????????
if?(s.Status?!=?X509ChainStatusFlags.OfflineRevocation?&&?s.Status?!=?X509ChainStatusFlags.RevocationStatusUnknown)
????????????????
{
????????????????????
return?false;
????????????????}

????????????}

????????}

????????
return?true;
????}

????
//該方法從本地計(jì)算機(jī)的個(gè)人證書區(qū)域按證書序列號(hào)查找指定的證書用于服務(wù)器身份驗(yàn)證
????
//以及打印出證書的詳細(xì)信息
????private?static?X509Certificate?GetServerCert(string?serialNumber)
????
{
????????X509Store?store?
=?new?X509Store(StoreName.My,?StoreLocation.CurrentUser);
????????
try
????????
{
????????????store.Open(OpenFlags.ReadOnly);
????????????X509Certificate2Collection?certificate?
=
????????????????????store.Certificates.Find(X509FindType.FindBySerialNumber,
????????????????????????????????????????????serialNumber,?
true);
????????????X509Certificate2?x509?
=?certificate[0];
????????????
byte[]?rawdata?=?x509.RawData;
????????????Console.WriteLine(
"509?count?:{0}",?store.Certificates.Count);
????????????Console.WriteLine(
"Content?Type:?{0}{1}",?X509Certificate2.GetCertContentType(rawdata),?Environment.NewLine);
????????????Console.WriteLine(
"Friendly?Name:?{0}{1}",?x509.FriendlyName,?Environment.NewLine);
????????????Console.WriteLine(
"Certificate?Verified?:?{0}{1}",?x509.Verify(),?Environment.NewLine);
????????????Console.WriteLine(
"Simple?Name:?{0}{1}",?x509.GetNameInfo(X509NameType.SimpleName,?true),?Environment.NewLine);
????????????Console.WriteLine(
"Signature?Algorithm:?{0}{1}",?x509.SignatureAlgorithm.FriendlyName,?Environment.NewLine);
????????????Console.WriteLine(
"Private?Key:?{0}{1}",?x509.PrivateKey.ToXmlString(false),?Environment.NewLine);
????????????Console.WriteLine(
"Public?Key:?{0}{1}",?x509.PublicKey.Key.ToXmlString(false),?Environment.NewLine);
????????????Console.WriteLine(
"Certificate?Archived?:?{0}{1}",?x509.Archived,?Environment.NewLine);
????????????Console.WriteLine(
"Length?of?Raw?Data:?{0}{1}",?x509.RawData.Length,?Environment.NewLine);
????????????Console.WriteLine(
"x509.SerialNumber:?{0}{1}",?x509.SerialNumber,?Environment.NewLine);

????????????
if?(certificate.Count?>?0)
????????????????
return?(certificate[0]);
????????????
else
????????????????
return?(null);
????????}

????????
catch?(Exception?ex)
????????
{
????????????Console.WriteLine(ex);
????????????
return?null;
????????}

????????
finally
????????
{
????????????store.Close();
????????}

????}

}

?

控制臺(tái)代碼
?static?void?Main(string[]?args)
????????
{
????????????
try
????????????
{
????????????????TCPServer_SSL?server?
=?new?TCPServer_SSL("127.0.0.1",?"8000");
????????????????server.Listen();
????????????}

????????????
catch?(Exception?ex)
????????????
{
????????????????Console.WriteLine(ex);
????????????}

????????????Console.Read();
????????}

?

客戶端

?

類庫(kù)
using?System;
using?System.Net.Sockets;
using?System.Net;
using?System.Net.Security;
using?System.Security.Cryptography.X509Certificates;
using?System.Text;
class?TCPClient_SSL
{
????
private?TcpClient?_client?=?null;
????
private?IPAddress?_address?=?IPAddress.Parse("127.0.0.1");
????
private?int?_port?=?5;
????
private?IPEndPoint?_endPoint?=?null;

????
public?TCPClient_SSL(string?address,?string?port)
????
{
????????_address?
=?IPAddress.Parse(address);
????????_port?
=?Convert.ToInt32(port);
????????_endPoint?
=?new?IPEndPoint(_address,?_port);
????}


????
public?void?ConnectToServer(string?msg)
????
{
????????
try
????????
{
????????????
using?(_client?=?new?TcpClient())
????????????
{
????????????????_client.Connect(_endPoint);

????????????????
//SslStream第一個(gè)參數(shù)是一個(gè)流,可以是由用Socket類new的一個(gè)NetworkStream
????????????????
//第二個(gè)參數(shù)為false的時(shí)候,關(guān)閉sslStream就會(huì)關(guān)閉對(duì)應(yīng)的NetworkStream
????????????????
//第三個(gè)參數(shù)是一個(gè)回調(diào),用來(lái)控制服務(wù)端的驗(yàn)證
????????????????using?(SslStream?sslStream?=?new?SslStream(_client.GetStream(),
????????????????????????????????
false,?new?RemoteCertificateValidationCallback(
????????????????????????????????????ValidateServerCertificate)))
????????????????
{

????????????????????X509CertificateCollection?cert?
=?new?X509CertificateCollection();
????????????????????
//下面是從一個(gè)導(dǎo)出證書文件里加載證書
????????????????????X509Certificate?cer?=?X509Certificate2.CreateFromCertFile("c://certs//huhao.cer");
????????????????????cert.Add(cer);
????????????????????
//AuthenticateAsClient方法第一個(gè)參數(shù)要寫服務(wù)端證書的名字,和服務(wù)器的機(jī)器名和dns名應(yīng)一致
????????????????????
//第二個(gè)參數(shù)是一個(gè)證書集合,如果是多個(gè)證書,可以在一個(gè)回調(diào)函數(shù)里選擇指定證書用以驗(yàn)證客戶端
????????????????????
//第三個(gè)參數(shù)指定安全傳輸?shù)膮f(xié)議,可以是ssl,tls的不同版本
????????????????????
//最后一個(gè)參數(shù)表示是否檢查吊銷證書列表,吊銷證書是定時(shí)推給服務(wù)器的,驗(yàn)證起來(lái)比較耗性能
????????????????????sslStream.AuthenticateAsClient("ms-7fa82788ed1e",?cert,?System.Security.Authentication.SslProtocols.Tls,?false);
????????????????????sslStream.ReadTimeout?
=?5000;
????????????????????sslStream.WriteTimeout?
=?5000;

????????????????????
//?Get?the?bytes?to?send?for?the?message.
????????????????????byte[]?bytes?=?Encoding.ASCII.GetBytes(msg);

????????????????????
//?Send?message.
????????????????????Console.WriteLine("Sending?message?to?server:?"?+?msg);

????????????????????
//這里可以使用BeginWrite
????????????????????sslStream.Write(bytes,?0,?bytes.Length);

????????????????????
//?Get?the?response.
????????????????????
//?Buffer?to?store?the?response?bytes.
????????????????????bytes?=?new?byte[1024];

????????????????????
//?Display?the?response.
????????????????????
//這里可以使用BeginRead
????????????????????int?bytesRead?=?sslStream.Read(bytes,?0,?bytes.Length);
????????????????????
string?serverResponse?=?Encoding.ASCII.GetString(bytes,?0,
??????????????????????????bytesRead);
????????????????????Console.WriteLine(
"Server?said:?"?+?serverResponse);
????????????????}

????????????}

????????}

????????
catch?(SocketException?e)
????????
{
????????????Console.WriteLine(
"There?was?an?error?talking?to?the?server:?{0}",
????????????e.ToString());
????????}

????}



????
private?bool?ValidateServerCertificate(object?sender,
???????????????????????????????????????????????X509Certificate?certificate,
???????????????????????????????????????????????X509Chain?chain,
???????????????????????????????????????????????SslPolicyErrors?sslPolicyErrors)
????
{
????????
if?(sslPolicyErrors?==?SslPolicyErrors.None)
????????
{
????????????
return?true;
????????}

????????
else
????????
{
????????????
if?(sslPolicyErrors?==?SslPolicyErrors.RemoteCertificateChainErrors)
????????????
{
????????????????Console.WriteLine(
"The?X509Chain.ChainStatus?returned?an?array?"?+
???????????????????
"of?X509ChainStatus?objects?containing?error?information.");
????????????}

????????????
else?if?(sslPolicyErrors?==
?????????????????????SslPolicyErrors.RemoteCertificateNameMismatch)
????????????
{
????????????????Console.WriteLine(
"There?was?a?mismatch?of?the?name?"?+
??????????????????
"on?a?certificate.");
????????????}

????????????
else?if?(sslPolicyErrors?==
?????????????????????SslPolicyErrors.RemoteCertificateNotAvailable)
????????????
{
????????????????Console.WriteLine(
"No?certificate?was?available.");
????????????}

????????????
else
????????????
{
????????????????Console.WriteLine(
"SSL?Certificate?Validation?Error!");
????????????}

????????}


????????Console.WriteLine(Environment.NewLine?
+
??????????????????????????
"SSL?Certificate?Validation?Error!");
????????Console.WriteLine(sslPolicyErrors.ToString());

????????
return?false;
????}

}



控制臺(tái)

static?void?Main(string[]?args)
????????
{
????????????
try
????????????
{
????????????????TCPClient_SSL?client?
=?new?TCPClient_SSL("127.0.0.1",?"8000");
????????????????client.ConnectToServer(
"11111");
????????????}

????????????
catch?(Exception?ex)
????????????
{
????????????????Console.WriteLine(ex);
????????????}

????????????Console.Read();
????????}

?

注意事項(xiàng)

1.???????? 如果TcpServer是一個(gè)windows服務(wù),用于服務(wù)端的證書不能用X509Certificate2.CreateFromCertFile方法加載導(dǎo)出的證書文件來(lái)獲取,而應(yīng)該用相關(guān)API來(lái)讀取本地計(jì)算機(jī)證書存儲(chǔ)器的my區(qū)域的證書,查找可以按證書序列號(hào)來(lái)查,具體代碼大約如下。

X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);

?? ?????????store.Open(OpenFlags.ReadOnly);

??????????? X509Certificate2Collection cert = store.Certificates.Find(X509FindType.FindBySerialNumber,

??????????? “611cea09000000000002”, false);

??????????? _certificate = cert[0];

2.???????? 如果是服務(wù)端是windows服務(wù),由于windows服務(wù)運(yùn)行賬戶是本地系統(tǒng)賬戶,并不是某個(gè)具體用戶,所以這時(shí)候用于服務(wù)端驗(yàn)證的證書應(yīng)該導(dǎo)入到本地計(jì)算機(jī)的my(個(gè)人)區(qū)域,然后本地計(jì)算的“受信任的根證書頒發(fā)機(jī)構(gòu)“要導(dǎo)入客戶端證書的CA證書(在客戶端證書申請(qǐng)頁(yè)有下載鏈接)。

3.???????? 出現(xiàn)“啟用服務(wù)端SSL必須使用關(guān)聯(lián)私鑰的證書“(The server mode SSL must use a certificate with the associated private key.)是因?yàn)榉?wù)端用的證書是從文件里取的,而不是通過(guò)證書存儲(chǔ)API取出來(lái)的,一般是這個(gè)問(wèn)題。

4.???????? 出現(xiàn)“沒(méi)有識(shí)別提供給安全軟件包的憑證“(System.Net.SSPIWrapper.AcquireCredentialsHandle方法)的錯(cuò)誤,可能是因?yàn)槟愕臋C(jī)器是虛擬機(jī),或者你試著重啟一下試試能否解決,該問(wèn)題出現(xiàn)后,代碼幾乎沒(méi)變,后來(lái)就好了。

5.???????? 通過(guò)證書申請(qǐng)頁(yè)面申請(qǐng)的證書一般會(huì)安裝在當(dāng)前用戶的個(gè)人存儲(chǔ)區(qū),如果要把這個(gè)證書安裝到計(jì)算機(jī)里,可以在證書管理控制臺(tái)里把用戶個(gè)人區(qū)域里的證書連私鑰導(dǎo)出成pfx文件(不是.cer文件),然后在在證書管理控制臺(tái)(開(kāi)始-運(yùn)行-輸入mmc.exe,在添加刪除管理單元里把“證書“單元添加進(jìn)來(lái),可以選擇當(dāng)前用戶和計(jì)算機(jī))里導(dǎo)入到計(jì)算機(jī)的個(gè)人區(qū)域里。

6.???????? 可以使用SslStream的異步讀寫方法來(lái)提高性能

7.???????? 從證書存儲(chǔ)區(qū)獲取證書的時(shí)候用證書序列號(hào)比較容易精確的獲取證書,比用subject等要準(zhǔn)確

8.???????? SslStream.AuthenticateAsClientdtargetHost參數(shù)為客戶端驗(yàn)證的服務(wù)端證書名稱,就是服務(wù)器認(rèn)證證書的“頒發(fā)給“字段。這里一定要寫對(duì),既不是CA的服務(wù)器地址,也不是類似http://ms-onlytiancai/certsrv/的字符串,也不是TcpServer的地址(實(shí)際上是TcpServernetbios名稱或dns名稱,和申請(qǐng)服務(wù)器證書時(shí)的姓名字段是一個(gè),必須相同)。如果填寫其它字符串,在客戶端驗(yàn)證的時(shí)候會(huì)出RemoteCertificateNameMismatch錯(cuò)誤。

https webServices

服務(wù)端配置SSL(https)

1.???????? IIS的默認(rèn)網(wǎng)站的屬性-目錄安全性-安全通信-服務(wù)器證書對(duì)話框里,選擇新建一個(gè)證書,按照向?qū)?#xff0c;一路向下,到“站點(diǎn)公用名稱列”,在“公用名稱”里輸入服務(wù)器的dns名稱或者netbios名稱,這里一定要填寫對(duì),最后會(huì)在硬盤上生成一個(gè)cerreq.txt文件的服務(wù)器證書申請(qǐng)單。

2.???????? 把上一步生成的申請(qǐng)單傳給CA,在CA服務(wù)器的“證書頒發(fā)機(jī)構(gòu)”管理器上右鍵點(diǎn)“新建證書申請(qǐng)”,在彈出的對(duì)話框里選擇cerreq.txt,確定后“掛起的證書”節(jié)點(diǎn)會(huì)多一個(gè)證書申請(qǐng),右鍵點(diǎn)“頒發(fā)”。頒發(fā)后在到“已頒發(fā)的證書”節(jié)點(diǎn)里找到剛剛頒發(fā)的證書,右鍵點(diǎn)“導(dǎo)出”,對(duì)話框里在“包含二進(jìn)制的列”下拉框里選擇“二進(jìn)制證書”,然后選擇“保存證書到一個(gè)文件”,最后會(huì)在硬盤上生成一個(gè).cer文件(應(yīng)該是帶私鑰的)。

3.???????? 在服務(wù)器上拷貝一下上一步生成的.cer文件,再在IIS屬性的目錄安全性-安全通信-服務(wù)器證書,彈出一個(gè)“歡迎使用web服務(wù)器證書向?qū)А睂?duì)話框,下一步后選擇“處理已掛起的證書申請(qǐng)”,下一步中選擇拷貝過(guò)來(lái)的.cer文件,再下一步選443端口。

4.???????? 然后在你的web服務(wù)的虛擬目錄-目錄安全性-安全通信-點(diǎn)編輯按鈕,把“要求安全通道(ssl)”的復(fù)選框打上,如果需要驗(yàn)證客戶端證書的話,在“客戶端證書”單選框列表里選擇“要求客戶端證書”。如果選擇了“要求客戶端證書”,可以在下面的“啟用客戶端證書映射”的“編輯”對(duì)話框里把證書映射到服務(wù)器的指定賬戶。

5.???????? 如果啟用了“要求客戶端證書”,服務(wù)器要信任客戶端證書的CA,具體操作如下。開(kāi)始-運(yùn)行,輸入mmc.exe。在控制臺(tái)里點(diǎn)文件-添加/刪除管理單元,選擇“證書”單元,然后點(diǎn)添加的時(shí)候選擇“計(jì)算機(jī)賬戶-本地計(jì)算機(jī)”(一定要選對(duì),如果選擇“我的用戶賬戶的話,只是當(dāng)前賬戶信任某個(gè)CA,當(dāng)前計(jì)算機(jī)不會(huì)信任指定CA的”)。然后在證書控制臺(tái)里的“受信任的頒發(fā)機(jī)構(gòu)”節(jié)點(diǎn)上右鍵點(diǎn)導(dǎo)入,把在證書申請(qǐng)頁(yè)面上下載的CA證書導(dǎo)入進(jìn)來(lái)。這樣這臺(tái)服務(wù)器就新人所有這個(gè)CA頒發(fā)的客戶端證書了。

客戶端訪問(wèn)

1、?先為客戶端申請(qǐng)一個(gè)客戶端證書,CA就用服務(wù)器計(jì)算機(jī)信任的CA

2、?編碼,如下,假設(shè)cxz計(jì)算機(jī)上有一個(gè)service的服務(wù),有個(gè)helloworld方法

?

源碼下載地址
http://files.cnblogs.com/onlytiancai/ssltest.rar

相關(guān)鏈接:
Securing Stream Data
http://codeidol.com/csharp/csharpckbk2/Security/Securing-Stream-Data/
構(gòu)建基于windows證書服務(wù)的公鑰基礎(chǔ)結(jié)構(gòu)
http://bbs.51cto.com/thread-426225-1-1.html
Windows 2000 公鑰基礎(chǔ)結(jié)構(gòu)詳解
http://www.cnblogs.com/coldwine/archive/2005/08/31/227071.html
聲明:本文代碼修改自相關(guān)鏈接的第一篇文章

原文出自:
http://www.cnblogs.com/onlytiancai/archive/2007/10/15/925425.html

?

using?System;
using?System.Net;
using?System.Net.Security;
using?System.Security.Cryptography.X509Certificates;
using?CallSslWebService.cxz;

namespace?CallSslWebService
{
????
class?Program
????{
????????
static?void?Main(string[]?args)
????????{
????????????
try
????????????{
????????????????
//掛接驗(yàn)證服務(wù)端證書的回調(diào)
????????????????ServicePointManager.ServerCertificateValidationCallback?=?RemoteCertificateValidationCallback;?

????????????????cxz.Service?service?
=?new?Service();?//實(shí)例一個(gè)web服務(wù)

????????????????
//如果web服務(wù)沒(méi)有啟用匿名訪問(wèn),要聲明credentials
????????????????ICredentials?credentials?=?new?NetworkCredential("administrator",?"1234%^@");
????????????????service.Credentials?
=?credentials;
????????????????
????????????????
//如果服務(wù)器要求提供客戶端證書,下面代碼提供了客戶端證書
????????????????X509Certificate?cer?=?X509Certificate.CreateFromCertFile("C://certs//client.cer");
????????????????service.ClientCertificates.Add(cer);

????????????????
//調(diào)用web服務(wù)
????????????????Console.WriteLine(service.HelloWorld());
????????????}
????????????
catch?(Exception?ex)
????????????{
????????????????Console.WriteLine(ex);
????????????}
????????????Console.Read();
????????}

????????
public?static?bool?RemoteCertificateValidationCallback(Object?sender,
????????????X509Certificate?certificate,
????????????X509Chain?chain,
????????????SslPolicyErrors?sslPolicyErrors)
????????{
????????????
//如果沒(méi)有錯(cuò)就表示驗(yàn)證成功
????????????if?(sslPolicyErrors?==?SslPolicyErrors.None)
????????????????
return?true;
????????????
return?false;
????????}
????}
}

ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.NETDEVFX.v20.chs/cpref10/html/T_System_Net_Security_SslStream_Members.htm

提供一個(gè)用于客戶端-服務(wù)器通信的流,此流使用安全套接字層 (SSL) 安全協(xié)議對(duì)服務(wù)器及客戶端(可選)進(jìn)行身份驗(yàn)證。

下表列出了由 SslStream 類型公開(kāi)的成員。

轉(zhuǎn)載于:https://www.cnblogs.com/BinZeng/p/3373434.html

總結(jié)

以上是生活随笔為你收集整理的用TLS实现安全TCP传输及配置和访问https的web服务(转)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。