背景

在三方接口对接中,偶尔会遇到需要传递证书的情况,这种方式其实是在SSL握手过程中会同时验证客户端和服务器的身份,这就是我们常说的 双向认证

双向认证需要服务器和客户端提供身份认证,只能是服务器允许的客户方能访问,安全性相对于要高一些。

下面老黄用几个小例子来演示一下双向认证的简单应用。

准备工作

由于离不开证书,所以我们需要提前生成好几个证书,这里用 OpenSSL 来生成一个自签名的。

2 个根证书,1 个服务端证书,2个不是同一个根证书下面的客户端证书

# 根证书
openssl genrsa -out ca.key 4096
openssl req -new -key ca.key -out ca.csr -days 365
openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt -days 365# 服务端证书
openssl genrsa -out server.key 4096
openssl req -new -key server.key -out server.csr -days 365
openssl x509 -req -in server.csr -out server.crt -CA ca.crt  -CAkey ca.key  -CAcreateserial -days 365
openssl pkcs12 -export -in server.crt -inkey server.key -out server.p12# 客户端证书
openssl genrsa -out client.key 4096
openssl req -new -key client.key -out client.csr -days 365
openssl x509 -req -in client.csr -out client.crt -CA ca.crt  -CAkey ca.key  -CAcreateserial -days 365
openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12

最后会有下面几个文件要在后面的演示中用到:ca.crtserver.p12server.crtserver.keyclient.p12client2.p12

下面先来看看 ASP.NET Core 直接对外的情况,也就是不依赖 nginx 或 IIS 的情况。

ASP.NET Core

基于 minimal api 来演示,主要是在 ConfigureKestrel 做处理。

var builder = WebApplication.CreateBuilder(args);builder.WebHost.ConfigureKestrel(x =>
{x.Listen(IPAddress.Any, 443, listenOptions =>{var serverCertificate = new X509Certificate2("server.p12", "abc123");var httpsConnectionAdapterOptions = new HttpsConnectionAdapterOptions(){// must provide a valid certificate for authenticationClientCertificateMode = ClientCertificateMode.RequireCertificate,SslProtocols = System.Security.Authentication.SslProtocols.Tls12,ClientCertificateValidation = (cer, chain, error) =>{// valid the client certificate by you way.return CusSSLLib.CaHelper.Valid(cer, chain, error);},ServerCertificate = serverCertificate};listenOptions.UseHttps(httpsConnectionAdapterOptions);});
});

这里最核心的是 HttpsConnectionAdapterOptions

ServerCertificate 设置成我们上面生成的服务端证书。

ClientCertificateMode 设置成 RequireCertificate,表示客户端在调用的时候必须要传递证书。

ClientCertificateValidation 就是验证客户端证书的逻辑,这里可以自定义,示例里面的验证逻辑主要针对不被信任的根证书做了验证。

首先是从资源文件读取了根证书,然后再去判断客户端证书是否匹配。

到这里的话,服务端已经可以了。

这个时候从浏览器访问,大概会看到这个提示。

下面写个控制台用 HttpClient 来访问看看。

void DoOk()
{var handler = new HttpClientHandler();handler.ClientCertificateOptions = ClientCertificateOption.Manual;handler.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls | SslProtocols.None | SslProtocols.Tls11;try{// add client certificatevar crt = new X509Certificate2(Path.Combine(Directory.GetCurrentDirectory(), "client.p12"), "123456");handler.ClientCertificates.Add(crt);}catch (Exception e){Console.WriteLine(e.Message);}handler.ServerCertificateCustomValidationCallback = (message, cer, chain, errors) =>{// valid server certificatereturn CusSSLLib.CaHelper.Valid(cer, chain, errors);};var client = new HttpClient(handler);var url = "https://localhost/WeatherForecast";var response = client.GetAsync(url).Result;Console.WriteLine(response.IsSuccessStatusCode);var result = response.Content.ReadAsStringAsync().Result;Console.WriteLine(result);
}

这里要注意,由于服务端用的证书也是自己签名的,所以这里的验证也要放开,想省事的话,可以直接 return true;,不过并不建议这样操作。

下面是运行的结果,是可以正常访问并返回结果的。

我们再换一张不是同一个根证书的客户端证书。

不出意外的不能正常访问。

不过上面这种情况在实际应用的时候会偏少一点,大部分还是会挂在反向代理或云负载均衡上面的。

下面先来看看 nginx 的吧。

nginx 反向代理

webapi 这一块,创建一个项目,有一个可以访问的接口即可,不用添加其他东西,因为证书这一块的内容都是在 nginx 那一层做了,webapi做原来该做的事情即可。

下面是 nginx 的配置文件

server {listen       443 ssl;server_name  localhost;# server certificatessl_certificate  /etc/nginx/ssl/server.crt;ssl_certificate_key /etc/nginx/ssl/server.key;# root certificatessl_client_certificate /etc/nginx/ssl/ca.crt;# open client certificate verifyssl_verify_client on;ssl_session_timeout  5m;            location / {proxy_pass http://webapi;index  index.html;}}

重点关注 ssl_verify_clientssl_client_certificate

一个是配置开启客户端证书的认证,一个是验证的客户端证书的关键。

这里的 ssl_client_certificate 用了根证书,为的是可以验证多个客户端证书,当然这里也可以用客户端证书。

把 webapi 和 nginx 都运行起来。

这个时候访问,就会提示, No required SSL certificate was sent。

用上面的控制台,再访问看看。

正确的证书,可以正常返回,错误的证书会返回 400 The SSL certificate error。

基于反向代理的话,操作起来就简单了一点。

如果是云负载均衡,只需要按他们的要求上传对应的证书即可。

讲了 nginx,不讲讲 IIS,好像有点说不过去。

那就再看看 IIS 的配置吧。

IIS 部署

在 Windows 服务器安装好 IIS 和托管捆绑包后,要先把我们的根证书安装到可信的根证书里面。

然后进行部署,绑定好服务端证书后,确认可以正常访问。

然后进行双向认证的配置。

在对应站点上面的 SSL 配置,把 要求 SSL必需 两个勾上即可。

后面再访问的时候,就会提示选择证书

选择正确的证书后就可以正常访问了。

然后我们再用前面的控制台程序访问,结果如下。

可以发现和前面的结果是一样的,不同的是错误返回的内容不一样。

上面提到的都是一些自建的场景,其实对云负载均衡的结合使用也是 OK 的。

总结

双向认证,在一些安全要求比较高的场景下,用途还是比较大的,相比较单向认证的话会麻烦一些。

参考资料

  • https://michielsioen.be/2020-10-17-mutual-ssl-linux/

  • https://docs.nginx.com/nginx/admin-guide/security-controls/securing-http-traffic-upstream/

  • https://learn.microsoft.com/en-us/iis/manage/configuring-security/how-to-set-up-ssl-on-iis

聊一聊HTTPS双向认证的简单应用相关推荐

  1. TurboMail邮件系统支持HTTPS双向认证

    2019独角兽企业重金招聘Python工程师标准>>> HTTP单向认证已经被普遍应用,而对企业邮箱安全保密要求更加严格的企事业单位,例如国家保密局等单位,为了达到闭环的安全加密要求 ...

  2. 巧用 Nginx 快速实现 HTTPS 双向认证

    1.原理 双向认证,顾名思义,客户端和服务器端都需要验证对方的身份,在建立 HTTPS 连接的过程中,握手的流程比单向认证多了几步.单向认证的过程,客户端从服务器端下载服务器端公钥证书进行验证,然后建 ...

  3. HTTPS双向认证(Mutual TLS authentication)

    HTTPS双向认证(Mutual TLS authentication) 双向认证,顾名思义,客户端和服务器端都需要验证对方的身份,在建立Https连接的过程中,握手的流程比单向认证多了几步.单向认证 ...

  4. https 双向认证开发实践

    https双向认证 证书如何使用 一.概念介绍 1.https协议介绍 与http协议的区别 https协议简单来说就是http协议的基础上增加了SSL协议 ,从而来保证数据传输的安全性. SSL协议 ...

  5. tomcat实现https双向认证配置

    Tomcat实现https双向认证配置 1.生成证书库 2.jks转p12 3.证书库导出cer文件 4.证书库生成证书请求 5.对证书请求进行签名 6.例子 6.1创建证书库 6.2导出根证书 6. ...

  6. Ktor实现Https双向认证

    前言 Ktor依靠跨端的能力,使得我们可以统一前后端.多平台的网路开发体验,本篇讲解如何在Ktor中实现Https双向认证. 密钥库 双向认证简单来说就是前后端各自生成自己的密钥库(包含一对公私钥), ...

  7. Https双向认证Android客户端配置

    Https双向认证啊  做了两遍,第一遍懵懂状态处于 好不容易做好了,换服务器,一下子懵了,使出浑身解数又找了一遍,这下终于好了  快哭啦,必须滴要记录一下,以免以后遇到继续懵,这里用retrofit ...

  8. Spring实现HTTPS双向认证

    目录 前言 一.单向认证和双向认证 二.创建keyStore和trustStore 三.服务端配置 四.客户端配置 总结 参考链接 前言 本篇博客讲的主要是双向认证,通过一些简单案例来展示双向认证的配 ...

  9. android webview单向认证,android 让webview支持自签名证书https 双向认证(SSL)

    最近完成一个项目,安全级别比较高.所以涉及到https双向认证,在网上找了很多资料都没有完美的解决方案.最后参考了org.sandrob.sslexample的实现方式,结合实际情况才完成该技术难题, ...

最新文章

  1. 任意多相机系统的SLAM重设计
  2. 归一化 vs 标准化 定量的分析
  3. 关于lucene的书
  4. 学习Java编程-Java Timezone类常见问题
  5. 【学习笔记】MOOC 数学文化赏析 笔记
  6. Android 编码规范:(五)避免创建不必要的对象
  7. python中getattr()的用法
  8. LeetCode 73. Set Matrix Zeroes
  9. Deep Learning ——Yann LeCun,Yoshua BengioGeoffrey Hinton
  10. JavaSE——Java8之Stream流
  11. dreamweaver代码提示失效
  12. python 物理引擎_第十六章:物理引擎
  13. 静态测试和动态测试有何区别
  14. OpenCV每日函数 WeChat QR 微信二维码检测器
  15. Python实现的简易HTTP代理服务器
  16. 最全的人力资源行业精美报表模板,免费下载啦
  17. 北京科技大学计算机专业在哪个校区,北京科技大学有几个校区及校区地址
  18. 玩个游戏好难 Win10我的世界(Minecraft)下载
  19. 手机原来也能把照片制作成视频?1分钟包你学会,发朋友圈超有范
  20. 【分布式任务调度】(三)XXL-JOB调度中心对执行器的上下线感知实现原理

热门文章

  1. densepose与SMPL之IUV坐标转XYZ坐标
  2. drl 规则语言 语法_C语言基本语法规则
  3. 背包问题——01背包
  4. php exit 和die,PHP中的die()和exit()有什么区别?
  5. 【DP】BZOJ2708 木偶
  6. Memwatch简介
  7. Controlling GC pauses with the GarbageFirst Collector
  8. 【NLP】中文分词:原理及分词算法
  9. windows 10 ISO 纯净版 官方来源
  10. 调用ins api获取个人照片信息