SSL认证适用于localhost,但不适用于计算机名称或ip [英] SSL Certification works with localhost but not computer name or ip

查看:74
本文介绍了SSL认证适用于localhost,但不适用于计算机名称或ip的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个运行在服务器上的Web应用程序,它通过XDomainRequest发布了HTTP请求(由于IE9).

We have a web application running on server and it posts http requests via XDomainRequest (because of IE9).

许多客户端计算机具有控制台应用程序,该应用程序通过套接字侦听器在端口上侦听.客户端使用其打开的Web应用程序 IE9浏览器,当他们单击链接时,网页将发送如下请求:

There are lots of client computers which have a console application listening on a port via socket listener. Clients open web application with their IE9 browsers and when they click on a link, the web page sends requests like that:

" https://localhost:portNumber/applicationName/doSomething " " https://计算机名:端口号/applicationName/doSomething " " https://ipAddress:portNumber/applicationName/doSomething "

发出第二个和第三个请求以控制台其他用户计算机的应用程序.

The second and third requests are made to console applications of other users' computers.

问题是,如果请求与本地主机一起提供,则控制台应用程序在读取传入数据和将响应发送回方面没有问题.但 如果请求附带计算机名称或IP地址,则浏览器将显示认证警告,并要求用户单击 继续浏览该网站(不推荐)"链接.

The problem is that if requests come with localhost, console application does not have a problem about reading incoming data and sending response back. But if the request comes with computer name or ip address then browser shows certification warning and wants user to click on "Continue to this web site (not recommended)" link.

我们认为可以通过代码创建三个不同的证书. 但是即使将sslstream与其中三个一起使用也是可能的,我们不能决定选择真正的证书,因为我们先进行身份验证然后再接收数据.因此,当我们捕获到传入的请求时,必须已经完成身份验证.

We thought creating three different certificates via code. But even using sslstream with three of them is possible we cannot decide to select true certification because we make authenticatiton first and then receive data. So when we catch incoming request the authentication must already be done.

另一种方法是强制套接字侦听器或sslstream将这三个请求都视为本地主机.因此,对于每一个身份验证都将作为localhost进行.但是我找不到真正的解决方法.

Another way is forcing socket listener or sslstream to behave all these three requests as if they are localhost. So for each one authentication will be made as localhost. But I could not find an actual way for that.

这是代码.我给出代码是因为SslStream的用法可能不正确.

Here is the code. I give the code because maybe there is some wrong usage of SslStream.

using System;
using System.Net.Sockets;
using System.Net;
using System.Configuration;
using System.Security.Cryptography.X509Certificates;
using System.Windows.Forms;
using System.IO;
using System.Net.Security;
using System.Security.Authentication;
using System.Threading;
using System.Text;

namespace StackOverFlowProject
{
    class StackOverFlowSample
    {
        private static ManualResetEvent _manualResetEvent = new ManualResetEvent(false);
        private static X509Certificate _cert = null;

        static void Main(string[] args)
        {
            StackOverFlowSample stackOverFlowSample = new StackOverFlowSample();
            stackOverFlowSample.StartListening();
        }

        private void StartListening()
        {
            GetCertificate();

            IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 1234);

            if (localEndPoint != null)
            {
                Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                if (listener != null)
                {
                    listener.Bind(localEndPoint);
                    listener.Listen(10);

                    Console.WriteLine("Socket listener is running. Waiting for requests...");

                    listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
                }
            }
        }

        private static void GetCertificate()
        {
            byte[] pfxData = File.ReadAllBytes(Application.StartupPath + @"\" + "localhost.pfx");

            _cert = new X509Certificate2(pfxData, "password", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
        }


        private void AcceptCallback(IAsyncResult result)
        {
            Socket listener = null;
            Socket handler = null;
            StateObject state = null;
            SslStream sslStream = null;

            _manualResetEvent.Set();

            listener = (Socket)result.AsyncState;

            handler = listener.EndAccept(result);

            state = new StateObject();

            if (handler.RemoteEndPoint != null)
            {
                state.clientIP = ((IPEndPoint)handler.RemoteEndPoint).Address.ToString();
            }

            sslStream = new SslStream(new NetworkStream(handler, true));
            sslStream.AuthenticateAsServer(_cert, false, SslProtocols.Tls, true);

            sslStream.ReadTimeout = 100000;
            sslStream.WriteTimeout = 100000;

            state.workStream = sslStream;

            if (state.workStream.IsAuthenticated)
            {
                state.workStream.BeginRead(state.buffer, 0, StateObject.BufferSize, ReceiveCallback, state);
            }

            listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
        }

        private void ReceiveCallback(IAsyncResult result)
        {
            StateObject stateObject = null;
            SslStream sslStreamReader = null;

            byte[] byteData = null;

            stateObject = (StateObject)result.AsyncState;
            sslStreamReader = stateObject.workStream;

            int byteCount = sslStreamReader.EndRead(result);

            Decoder decoder = Encoding.UTF8.GetDecoder();
            char[] chars = new char[decoder.GetCharCount(stateObject.buffer, 0, byteCount)];
            decoder.GetChars(stateObject.buffer, 0, byteCount, chars, 0);
            stateObject.sb.Append(chars);

            if (byteCount > 0)
            {
                stateObject.totalReceivedBytes += byteCount;

                string[] lines = stateObject.sb.ToString().Split('\n');

                if (lines[lines.Length - 1] != "<EOF>")
                {
                    // We didn't receive all data. Continue reading...
                    sslStreamReader.BeginRead(stateObject.buffer, 0, stateObject.buffer.Length, new AsyncCallback(ReceiveCallback), stateObject);
                }
                else
                {
                    Console.WriteLine("We received all data. Sending response...");

                    byteData = Encoding.UTF8.GetBytes("Hello! I received your request!");

                    string httpHeaders = "HTTP/1.1" + "\r\n"
                                    + "Cache-Control: no-cache" + "\r\n"
                                    + "Access-Control-Allow-Origin: *" + "\r\n"
                                    + "\r\n";

                    byte[] byteHttpHeaders = Encoding.UTF8.GetBytes(httpHeaders);

                    byte[] concat = new byte[byteHttpHeaders.Length + byteData.Length];
                    Buffer.BlockCopy(byteHttpHeaders, 0, concat, 0, byteHttpHeaders.Length);
                    Buffer.BlockCopy(byteData, 0, concat, byteHttpHeaders.Length, byteData.Length);

                    stateObject.sslStreamReader = sslStreamReader;

                    sslStreamReader.BeginWrite(concat, 0, concat.Length, new AsyncCallback(SendCallback), stateObject);
                }
            }
        }

        private void SendCallback(IAsyncResult ar)
        {
            SslStream sslStreamSender = null;

            StateObject stateObject = (StateObject)ar.AsyncState;

            sslStreamSender = stateObject.sslStreamReader;
            sslStreamSender.EndWrite(ar);

            Console.WriteLine(stateObject.totalReceivedBytes.ToString() + " bytes sent to " + stateObject.clientIP + " address");

            sslStreamSender.Close();
            sslStreamSender.Dispose();
        }

    }

    public class StateObject
    {
        public SslStream workStream = null;

        public SslStream sslStreamReader = null;

        public const int BufferSize = 1024;
        public byte[] buffer = new byte[BufferSize];
        public StringBuilder sb = new StringBuilder();

        public string clientIP = "";

        public int totalReceivedBytes = 0;
    }
}

推荐答案

您遇到的证书警告实际上是名称不匹配错误,它表示SSL证书中的公用名(域名)与URL不匹配/address用于访问网站/服务器.

The certificate warning that you are encountering is really a name mismatch error, which indicates that the common name (domain name) in the SSL certificate does not match the URL/address used to access the web site/server.

https://www.sslshopper.com/ssl-certificate- name-mismatch-error.html

在您的使用场景中,您可能希望从localhost和ip地址过渡到使用计算机名称的简单域模型. (例如computerName.someDomain.com)

In your usage scenario, you may want to transition away from localhost and ip addresses in favor of a simple domain model that leverages the computer name. (e.g. computerName.someDomain.com)

然后,您可以获得通配符证书(例如*.someDomain.com),该证书可用于验证进程间通信.

Then, you could obtain a wildcard certificate (e.g. *.someDomain.com) which could be used to authenticate inter-process communication.

https://www.sslshopper.com/best-ssl-wildcard- certificate.html

这篇关于SSL认证适用于localhost,但不适用于计算机名称或ip的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆