Winform发布https

为啥要用Winfrom发布https的web服务呢?就得说的不守信用的w3c协议了。原来谷歌浏览器支持https调用ws,在90版本之后直接禁止所有https访问非https资源了。不得不说垄断任性啊。

为了解决新版浏览器在https时候无法驱动cs程序的问题,再引入一个调用通道,就是winform发布https。

首先用linux得到证书

# 生成私钥
openssl genrsa -aes256 -passout "pass:mypassword" -out key.pem 4096
# 生成公钥
openssl req -new -x509 -days 3650 -key key.pem -passin "pass:mypassword" -out cert.csr -subj "/C=CN/ST=BeiJing/L=BeiJing/O=Gongshi/OU=Group/CN=www.baidu.com//emailAddress=zzzz@qq.com.cn"
# 打包为pfx
openssl pkcs12 -export -in cert.csr -inkey key.pem -out dotnet.linux.pfx


这样就得到了.pfx的证书文件给winform程序使用

winform代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.IO;
using System.Diagnostics;

namespace Http
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            LISHttpsServer service = new LISHttpsServer();
            service.InitServer("8080");
        }


    }
}

包装的服务类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.IO;
using System.Diagnostics;

namespace Http
{
    /// <summary>
    /// 处理请求消息
    /// </summary>
    /// <param name="msg">消息</param>
    /// <param name="request">请求对象</param>
    /// <param name="response">回复对象</param>
    public delegate void DealRequestMsg(string msg,HttpListenerRequest request, HttpListenerResponse response); 

    /// <summary>
    /// http监听对象
    /// </summary>
    public class ZLZHttpsServer
    {
        /// <summary>
        /// 监听对象
        /// </summary>
        HttpListener httpobj = null;

        /// <summary>
        /// 处理消息回调
        /// </summary>
        DealRequestMsg DealMasg = null;

        /// <summary>
        /// 发送给js的消息
        /// </summary>
        public static Dictionary<string, Queue<string>> SendToJsMsg = new Dictionary<string, Queue<string>>();


        /// <summary>
        /// 初始化服务
        /// </summary>
        /// <param name="port"></param>
        public void InitServer(string port, DealRequestMsg dealMasg)
        {
            DealMasg = dealMasg;
            if (CheckCert("E=xxpt@xxx.com.cn, CN=xx.xx.com.cn, OU=xx, O=xx, L=xx, S=BeiJing, C=CN") == false)
            {
                InstallCACert(port);
            }
            //提供一个简单的、可通过编程方式控制的 HTTP 协议侦听器。此类不能被继承。
            httpobj = new HttpListener();
            //定义url及端口号,通常设置为配置文件
            httpobj.Prefixes.Add("https://+:"+port+"/");
            //启动监听器
            httpobj.Start();
            //异步监听客户端请求,当客户端的网络请求到来时会自动执行Result委托
            //该委托没有返回值,有一个IAsyncResult接口的参数,可通过该参数获取context对象
            httpobj.BeginGetContext(HttpResult, null);
        }

        /// <summary>
        /// 检查证书
        /// </summary>
        /// <param name="CN"></param>
        /// <returns></returns>
        private static bool CheckCert(string CN)
        {
            bool flag = false;
            X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
            try
            {
                store.Open(OpenFlags.MaxAllowed);
                X509Certificate2Enumerator enumerator = store.Certificates.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    X509Certificate2 current = enumerator.Current;
                    if (current.SubjectName.Name == CN)
                    {
                        flag = true;
                        return flag;
                    }
                }
            }
            finally
            {
                store.Close();
            }
            return flag;
        }

        /// <summary>
        /// 安装证书
        /// </summary>
        /// <param name="port"></param>
        /// <returns></returns>
        private bool InstallCACert(string port)
        {
            string s = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "dotnet.linux.pfx");
            X509KeyStorageFlags machineKeySet = X509KeyStorageFlags.MachineKeySet;
            X509Certificate2 certificate = new X509Certificate2(s, "mypassword", machineKeySet);
            X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
            store.Open(OpenFlags.MaxAllowed);
            store.Add(certificate);
            store.Close();
            if (Environment.OSVersion.Version.Major > 5)
            {
                string str2 = "0.0.0.0:" + port;
                string cmd = string.Format("netsh http add sslcert ipport={0} certhash={1} appid={{391d625b-f844-4e72-a0b1-1ce1592b31eb}}", str2, certificate.Thumbprint);
                string str4 = Run(cmd);
            }
            return true;
        }

        /// <summary>
        /// 运行cmd
        /// </summary>
        /// <param name="cmd">命令</param>
        /// <returns></returns>
        public string Run(string cmd)
        {
            Process process1 = new Process();
            process1.StartInfo.FileName = "cmd.exe";
            process1.StartInfo.UseShellExecute = false;
            process1.StartInfo.RedirectStandardInput = true;
            process1.StartInfo.RedirectStandardOutput = true;
            process1.StartInfo.RedirectStandardError = true;
            process1.StartInfo.CreateNoWindow = true;
            Process process = process1;
            process.Start();
            cmd = string.IsNullOrEmpty(cmd) ? "exit" : ("if 1 equ 1 (" + cmd + ") & exit");
            process.StandardInput.WriteLine(cmd);
            process.StandardInput.AutoFlush = true;
            return "";
        }

        /// <summary>
        /// 接收http请求
        /// </summary>
        /// <param name="args"></param>
        private void HttpResult(IAsyncResult args)
        {
            //继续异步监听
            httpobj.BeginGetContext(HttpResult, null);
            var guid = Guid.NewGuid().ToString();
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine("接到新的请求:"+guid+",时间:"+DateTime.Now.ToString());
            //获得context对象
            var context = httpobj.EndGetContext(args);
            var request = context.Request;
            var response = context.Response;
            //允许跨域
            response.AddHeader("Access-Control-Allow-Origin", "*");
            response.AddHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS");
            response.AddHeader("Access-Control-Allow-Headers", "Content-Type,content-type,x-requested-with,NotReturn-Type");
            context.Response.ContentType = "text/plain;charset=UTF-8";
            context.Response.AddHeader("Content-type", "text/plain");
            context.Response.ContentEncoding = Encoding.UTF8;
            string returnObj = null;
            if (request.HttpMethod == "POST" && request.InputStream != null)
            {
                //处理客户端发送的请求并返回处理信息
                returnObj = HandleRequest(request, response);
            }
            else
            {
                returnObj = "Welcome to use the https print call channel, the service is published on port 18082";
            }
            var returnByteArr = Encoding.UTF8.GetBytes(returnObj);//设置客户端返回信息的编码
            try
            {
                using (var stream = response.OutputStream)
                {
                    //把处理信息返回到客户端
                    stream.Write(returnByteArr, 0, returnByteArr.Length);
                }
            }
            catch (Exception ex)
            {
            }
        }


        /// <summary>
        /// 处理请求
        /// </summary>
        /// <param name="request"></param>
        /// <param name="response"></param>
        /// <returns></returns>
        private string HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
        {
            string str = null;
            try
            {
                var byteList = new List<byte>();
                var byteArr = new byte[2048];
                int readLen = 0;
                int len = 0;
                //接收客户端传过来的数据并转成字符串类型
                do
                {
                    readLen = request.InputStream.Read(byteArr, 0, byteArr.Length);
                    len += readLen;
                    byteList.AddRange(byteArr);
                } 
                while (readLen != 0);
                str = Encoding.UTF8.GetString(byteList.ToArray(), 0, len);
                //调用处理
                if (DealMasg != null && str!="")
                {
                    DealMasg(str,request,response);
                }
                //看有没有积压的消息
                if (ZLZHttpsServer.SendToJsMsg.ContainsKey(request.Url.ToString()))
                {
                    Queue<string> quen = ZLZHttpsServer.SendToJsMsg[request.Url.ToString()];
                    if (quen.Count > 0)
                    {
                        string onemsg = quen.Dequeue();
                        return onemsg;
                    }
                }
                return "zlz-httpsret";
            }
            catch (Exception ex)
            {
                response.StatusDescription = "404";
                response.StatusCode = 404;
                return "在接收数据时发生错误:"+ex.Message;
            }
            response.StatusDescription = "200";
            response.StatusCode = 200;
            return "接收数据完成";
        }
    }
}


测试效果
在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小乌鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值