• .NET 证书加密 存储保存 IIS授权


    最近接到一个任务,加密DotNet项目的配置文件。配置文件里需要加密的地方一共有两块,一个是数据库连接字符串,一个是自定义的所有AppSettings。

    一开始接到这个任务我是拒绝的,因为压根不知道怎么加密,印象中的加密方式还停留在MD5。对于啥是对称加密,啥是非对称加密完全不认识。

    加密方式

    因为用的是DotNet所以打开微软Doc,希望能找到一点关于DotNet加密的说明文档。

    其中.Net安全性介绍了一些关于加密的方法。

    最常用的加密方式

    • 对称加密

    对称加密,使用单个密钥加密和解密数据(通常被用来加密大数据量的东西)。

    • 非对称加密

    非对称加密,分为公钥和私钥,利用公钥加密数据,由私钥解密。通常情况下用来保护对称加密的密钥。(在开发过程中发现,用公钥加密一个数据库连接字符串都会由于内容过长而报错)。对于待加密内容比较长的,可以使用分段加密的方式。

    数字证书

    一开始考虑使用对称方式加密配置文件,但是密钥的存放就是是一个很大的问题,想当然的就打算把密钥放在配置文件里。可是加密的意义何在呢?

    所以后来考虑使用非对称方式加密配置文件,利用公钥加密文件,然后利用私钥解密。

    存放公钥和私钥的最好工具是数字证书。

    通常情况下,数字证书分为两种,一种只有公钥,一种则是有公钥也有私钥。

    生成证书

    证书其实需要由第三方CA机构来生成的,当然也可以自己生成。

    Windows平台下微软提供了两种生成方式:

    数字证书的存储

    看了网上的很多博客,大部分是直接加载本地实体文件,比较高级的是把证书导入到计算机的存储区。

    证书存储有两种类型:

    • 本地用户
      • MY
      • Root
      • Trust
      • CA
      • UserDS
    • 当前用户
      • MY
      • Root
      • Trust
      • CA
      • UserDS

    本地用户除了MY以外应该都可以被当前用户继承

    导入证书

            //导入文件方法
            private static bool ImportPfxFile(string filePath, string password = null)
            {
                //证书安装到本地存储,根节点
                X509Store store = new X509Store(StoreName.TrustedPeople, StoreLocation.LocalMachine);
    
                try
                {
                    X509Certificate2 certificate = new X509Certificate2(filePath, password == null ? "" : password, X509KeyStorageFlags.MachineKeySet);
    
                    store.Open(OpenFlags.ReadWrite);
    
                    store.Remove(certificate);   //可省略
    
                    store.Add(certificate);
    
                    //File.Delete(filePath);
                    return true;
                }
                catch (System.Exception e)
                {
                    MessageBox.Show(e.Message);
                    return false;
                }
                finally
                {
                    store.Close();
                }
    
            }
    

    注意

    • 导入证书的时候注意证书存储标志X509KeyStorageFlags,一般情况下不推荐设置为可导出Exportable,所以利用私钥解密的时候,注意私钥的使用方式。

    • 对于证书密码,如果没有直接给null就可以了。

    关于给IIS授权的问题

    运行环境是IIS,经测试发现直接运行网站是没有权限获取证书的,需要给IIS用户授权才可以。

    这个IIS用户给我折腾死了。本来以为给 ASP.NET 授权就可以了,没想到不是的。经过一顿搜索终于明白了,需要授权的是对应程序池的名称。

    名称 状态 .NET CLR 版本 托管管道模式 标识 应用程序
    .NET v2.0 已启动 v2.0 集成 ApplicationPoolIdentity 0
    DefaultAppPool 已启动 v4.0 集成 ApplicationPoolIdentity 4

    比如网站的程序池是DefaultAppPool,就需要给DefaultAppPool用户授权。

    授权方式一

    第一种方式比较简单,利用MMC。

    • 命令行打开MMC
    • 添加证书节点
    • 将其他区的证书托动到个人
    • 右键证书》所有任务》管理私钥==》添加对应用户即可
    • 将证书托回到原来分区

    授权方式二

    第二种方式需要用到两个工具appcmd.exe和winhttpcertcfg.exe。

    appcmd.exe是一个IIS命令行工具,详细文档

    appcmd.exe一般会存放在C:WindowsSystem32inetsrvappcmd.exe

    这里的使用方式很简单即通过命令获得IIS所有程序池信息,执行以下命令

    
    C:WindowsSystem32inetsrvappcmd.exe list apppool
    
    //得到如下结果
    APPPOOL "DefaultAppPool" (MgdVersion:v4.0,MgdMode:Integrated,state:Started)
    APPPOOL "Classic .NET AppPool" (MgdVersion:v2.0,MgdMode:Classic,state:Started)
    APPPOOL ".NET v2.0 Classic" (MgdVersion:v2.0,MgdMode:Classic,state:Started)
    APPPOOL ".NET v2.0" (MgdVersion:v2.0,MgdMode:Integrated,state:Started)
    APPPOOL ".NET v4.5 Classic" (MgdVersion:v4.0,MgdMode:Classic,state:Started)
    APPPOOL ".NET v4.5" (MgdVersion:v4.0,MgdMode:Integrated,state:Started)
    
    

    .Net 执行此命令

    
        private Dictionary<string, object> MyCommand(string fileName, string argument)
            {
                try
                {
                    ProcessStartInfo startInfo = new ProcessStartInfo(fileName)
                    {
                        CreateNoWindow = true,
                        UseShellExecute = false,
                        RedirectStandardError = true,
                        RedirectStandardOutput = true,
                        Arguments = argument
                    };
    
                    //创建一个进程
                    Process pc = new Process();
                    pc.StartInfo = startInfo;
    
                    //启动进程
                    pc.Start();
    
                    //准备读出输出流和错误流
                    List<string> listOutPut = new List<string>();
                    List<string> listError = new List<string>();
                    pc.BeginOutputReadLine();
                    pc.BeginErrorReadLine();
    
                    pc.OutputDataReceived += (ss, ee) =>
                    {
                        listOutPut.Add(ee.Data);
                    };
    
                    pc.ErrorDataReceived += (ss, ee) =>
                    {
                        listError.Add(ee.Data);
                    };
                    //等待退出
                    pc.WaitForExit();
    
                    //关闭进程
                    pc.Close();
                    Dictionary<string, object> dic = new Dictionary<string, object>();
                    dic.Add("outPut", listOutPut);
                    dic.Add("error", listError);
                    return dic;
                }
                catch (Exception e)
                {
                    throw e;
                }
            }
    
    

    通过解析listOutPut可以得到程序池名称。

    接下来需要用到证书配置工具winhttpcertcfg.exe 详细文档

    利用如下命令即可完成授权

    
    winhttpcertcfg -g -c LOCAL_MACHINEMy -s MyCertificate -a TESTUSER
    
    //LOCAL_MACHINEMy:用户存储区
    //MyCertificate:证书名
    //TESTUSER:授权用户名,即listOutPut得到的程序池名称
    
    

    注意

    如果利用appcmd得到程序池名称后执行授权命令,报如下错

    
    Error: No account information was found.
    
    

    这说明程序池并非活跃状态,访问一下对应网站即可。

  • 相关阅读:
    Gitlab 11.0.3配置LDAP
    IntelliJ IDEA快速创建属性字段的get和set方法
    解决Maven引用POI的依赖,XSSFWorkbook依旧无法使用的问题
    解决方案看起来是受源代码管理,但无法找到它的绑定信息。保存解决方案的源代码管理设置的MSSCCPRJ.SCC文件或其他项可能己被删除。
    IntelliJ IDEA开发工具println报错的解决方法
    Eclipse开发工具printf打印方法提示报错的解决方法
    Java基础学习总结一(Java语言发展历史、JDK下载安装以及配置环境变量)
    浅谈JavaScript之function用括号包起来
    讲解JavaScript两个圆括号、自调用和闭包函数
    Visual Studio Code使用Open In Browser打开的是记事本
  • 原文地址:https://www.cnblogs.com/hoyu/p/10318598.html
Copyright © 2020-2023  润新知