到现在,我们已经完成了POS平台和前端的网络集成。不过,还是那句话:平台系统的网络安全是至关重要的。前一篇博客里我们尝试实现了gRPC ssl/tls网络连接,但测试时用的证书如何产生始终没有搞清楚。现在akka-http开发的ws同样面临HTTPS的设置和使用问题。所以,特别抽出这篇博文讨论一下数字证书的问题。

在正式的生产环境里数字证书应该是由第三方公证机构CA签发的,我们需要向CA提出申请。数字证书的申请、签发和验证流程如下:

) 服务⽅ S 向第三⽅方机构CA提交公钥、组织信息、个⼈信息(域名)等资料提出认证申请 (不需要提供私钥)

) CA 通过各种手段验证申请者所提供信息的真实性,如组织是否存在、 企业是否合法,是否拥有域名的所有权等

) 如信息审核通过,CA 会向申请者签发认证文件-证书。 证书包含以下信息:申请者公钥、申请者的组织信息和个⼈信息、签发机构 CA 信息、有效时间、证书序列号等信息的明⽂,同时包含一个签名的产⽣生算法:首先,使用散列函数计算出证书中公开明文信息的信息摘要,然后, 采用 CA 的私钥对信息摘要进⾏加密,这个密⽂就是签名了

) 客户端 C 向服务器 S 发出请求时,S 返回证书文件

) 客户端 C 读取证书中的相关的明⽂信息,采⽤相同的散列函数计算得到信息摘要, 然后,利用对应 CA 的公钥解密签名数据,对比证书的信息摘要,如果一致,则可以确认证书的合法性,即公钥合法

) 客户端 C 然后检验证书相关的域名信息、有效时间等信息

) 客户端 C 应内置信任 CA 的证书信息(包含公钥),如果 CA 不被信任,则找不到对应 CA 的证书,证书也会被判定非法

) 内置 CA 对应的证书称为根证书,颁发者和使⽤者相同,用 CA ⾃⼰的私钥签名,即⾃签名证书(此证书中的公钥即为 CA 的公钥,可以使用这个公钥对证书的签名进行校验,⽆需另外⼀份证书)

服务器端在通信中建立SSL加密渠道过程如下:

)客户端 C 发送请求到服务器端 S

) 服务器端 S 返回证书和公开密钥到 C,公开密钥作为证书的一部分传送

)客户端 C 检验证书和公开密钥的有效性,如果有效,则⽣成共享密钥并使⽤公开密钥加密发送到服务器端 S

) 服务器端 S 使⽤私有密钥解密数据,并用收到的共享密钥加密数据,发送到客户端 C 

) 客户端 C 使⽤用共享密钥解密数据

) SSL 加密通信渠道建立 ...

应该说,需要在客户端进行认证的应用场景不多。这种情况需要在客户端存放数字证书。像支付宝和一些银行客户端一般都需要安装证书。

好了,还是回到如何产生自签名证书示范吧。下面是一个标准的用openssl命令产生自签名证书流程:

在产生证书和密钥的过程中所有系统提问回答要一致。我们先假设密码统一为:123456

1、生成根证书私钥: rootCA.key:  openssl genrsa -des3 -out rootCA.key 2048

2、根证书申请 rootCA.csr:openssl req -new -key rootCA.key -out rootCA.csr

3、用申请rootCA.csr生成根证书 rootCA.crt:openssl x509 -req -days 365 -sha256 -extensions v3_ca -signkey rootCA.key -in rootCA.csr -out rootCA.crt

4、pem根证书 rootCA.pem:openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.pem

5、创建⼀个v3.ext⽂件,目的是产生X509 v3证书,主要目的是指定subjectAltName选项:

  authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS. = localhost
IP. = "192.168.11.189"
IP. = "192.168.0.189"
IP. = "132.232.229.60"
IP. = "118.24.165.225"
IP. = "129.28.108.238"

注意subjectAltName,这些都是可以信任的域名或地址。

6、构建证书密钥 server.key:openssl req -new -sha256 -nodes -out server.csr -newkey rsa:2048 -keyout server.key

7、用根证书rootCA产生自签证书 server.crt:openssl x509 -req -in server.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out server.crt -days 500 -sha256 -extfile v3.ext

上面这个过程需要不断重复回答同样的问题,很烦。可以用配置文件来一次性产生:

先构建一个ssl.cnf文件:

  [req]
prompt = no
default_bits =
default_md = sha256
distinguished_name = dn
x509_extensions = v3_req
[dn]
C=CN
ST=GuangDong
L=ShenZhen
O=Bayakala
OU=POS
CN=www.bayakala.com
emailAddress=admin@localhost
[v3_req]
keyUsage=keyEncipherment, dataEncipherment
extendedKeyUsage=serverAuth
subjectAltName=@alt_names
[alt_names]
DNS. = localhost
IP. = "192.168.11.189"
IP. = "192.168.0.189"
IP. = "132.232.229.60"
IP. = "118.24.165.225"
IP. = "129.28.108.238"

然后:openssl req -new -newkey rsa:2048 -sha1 -days 3650 -nodes -x509 -keyout server.key -out server.crt -config ssl.cnf

一个指令同时产生需要的server.crt,server.key。

除aubjectAltName外还要关注CN这个字段,它就是我们经常会遇到系统提问:你确定信任“域名”吗?中这个域名,也就是对外界开放的一个使用了数字证书的域名。

把crt,key抄写到main/resources目录下,然后在gRPC服务器配置证书:

trait gRPCServer {

  val serverCrtFile = new File(getClass.getClassLoader.getResource("server.crt").getPath)
val serverKeyFile = new File(getClass.getClassLoader.getResource("server.key").getPath) def runServer(service: ServerServiceDefinition): Unit = {
val server = NettyServerBuilder
.forPort()
.addService(service)
.useTransportSecurity(serverCrtFile,serverKeyFile)
.build
.start
// make sure our server is stopped when jvm is shut down
Runtime.getRuntime.addShutdownHook(new Thread() {
override def run(): Unit = {
server.shutdown()
server.awaitTermination()
}
})
} }

启动gRPC服务,运作正常。在看看客户端代码:

    val clientCrtFile = new File(getClass.getClassLoader.getResource("server.crt").getPath)
//或者 val clientCrtFile = new File(getClass.getClassLoader.getResource("rootCA.pem").getPath) //这样也行 val clientCrtFile: InputStream = getClass.getClassLoader.getResourceAsStream("rootCA.pem") val sslContextBuilder = GrpcSslContexts.forClient().trustManager(clientCrtFile) //build connection channel
val channel = NettyChannelBuilder
.forAddress("192.168.11.189",)
.negotiationType(NegotiationType.TLS)
.sslContext(sslContextBuilder.build())
// .overrideAuthority("192.168.1.3")
.build()

测试连接,gRPC SSL/TLS成功!

现在开始了解一下https证书的配置使用方法吧。看了一下akka-http关于server端HTTPS设置的例子,证书是嵌在HttpsConnectionContext类型里面的。还有就是akka-http使用的https证书格式只支持pkcs12,所以需要把上面用openssl产生的自签名证书server.crt转成server.p12。这个转换又需要先产生证书链certificate-chain chain.pem:

1)产生certificate-chain:  cat server.crt rootCA.crt > chain.pem

2) server.crt转换成server.p12: openssl pkcs12 -export -name servercrt -in chain.pem -inkey server.key -out server.p12

https server 测试代码:

//#imports
import java.io.InputStream
import java.security.{ SecureRandom, KeyStore }
import javax.net.ssl.{ SSLContext, TrustManagerFactory, KeyManagerFactory } import akka.actor.ActorSystem
import akka.http.scaladsl.server.{ Route, Directives }
import akka.http.scaladsl.{ ConnectionContext, HttpsConnectionContext, Http }
import akka.stream.ActorMaterializer
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives._ //#imports object HttpsDemo extends App { implicit val httpSys = ActorSystem("httpSystem")
implicit val httpMat = ActorMaterializer()
implicit val httpEC = httpSys.dispatcher val password: Array[Char] = "".toCharArray // do not store passwords in code, read them from somewhere safe! val ks: KeyStore = KeyStore.getInstance("PKCS12")
val keystore: InputStream = getClass.getClassLoader.getResourceAsStream("server.p12")
ks.load(keystore, password) val keyManagerFactory: KeyManagerFactory = KeyManagerFactory.getInstance("SunX509")
keyManagerFactory.init(ks, password) val tmf: TrustManagerFactory = TrustManagerFactory.getInstance("SunX509")
tmf.init(ks) val sslContext: SSLContext = SSLContext.getInstance("TLS")
sslContext.init(keyManagerFactory.getKeyManagers, tmf.getTrustManagers, new SecureRandom)
val https: HttpsConnectionContext = ConnectionContext.https(sslContext) val route = get { complete("Hello world!") } val (port, host) = (,"192.168.11.189") val bindingFuture = Http().bindAndHandle(route,host,port,connectionContext = https) println(s"Https Server running at $host $port. Press any key to exit ...") scala.io.StdIn.readLine() bindingFuture.flatMap(_.unbind())
.onComplete(_ => httpSys.terminate()) }

用safari连接https://192.168.11.189:50081/, 弹出窗口一堆废话后还是成功连接上了。

Akka-CQRS(13)- SSL/TLS for gRPC and HTTPS:自签名证书产生和使用的更多相关文章

  1. 跟我一起学Go系列:Go gRPC 安全认证机制-SSL/TLS认证

    Go gRPC 系列: 跟我一起学Go系列:gRPC 拦截器使用 跟我一起学Go系列:gRPC 入门必备 第一篇入门说过 gRPC 底层是基于 HTTP/2 协议的,HTTP 本身不带任何加密传输功能 ...

  2. https请求时出错:Could not establish trust relationship for the SSL/TLS secure channel

    当我在用NET命名空间下获取URL的时候,提示如下错误: The underlying connection was closed: Could not establish trust relatio ...

  3. 在 Tomcat 中配置 SSL/TLS 以支持 HTTPS

    本件详细介绍了如何通过几个简单步骤在 Tomcat 中配置 SSL/TLS .使用 JDK 生成自签名的证书,最终实现在应用中支持 HTTPS 协议. 生产密钥和证书 Tomcat 目前只能操作 JK ...

  4. SSL/TLS All In One

    SSL/TLS All In One HTTPS SSL/TLS 的工作原理 https://www.websecurity.digicert.com/zh/cn/security-topics/ho ...

  5. Akka-CQRS(10)- gRPC on SSL/TLS 安全连接

    使用gRPC作为云平台和移动前端的连接方式,网络安全应该是必须考虑的一个重点.gRPC是支持ssl/tls安全通讯机制的.用了一个周末来研究具体使用方法,实际上是一个周末的挖坑填坑过程.把这次经历记录 ...

  6. .NET Core下使用gRpc公开服务(SSL/TLS)

    一.前言 前一阵子关于.NET的各大公众号都发表了关于gRpc的消息,而随之而来的就是一波关于.NET Core下如何使用的教程,但是在这众多的教程中基本都是泛泛而谈,难以实际在实际环境中使用,而该篇 ...

  7. SSL/TLS 高强度加密: 常见问题解答

    关于这个模块 mod_ssl 简史 mod_ssl会受到Wassenaar Arrangement(瓦森纳协议)的影响吗? mod_ssl 简史 mod_ssl v1 最早在1998年4月由Ralf ...

  8. 在 ASP.NET MVC 中使用 HTTPS (SSL/TLS)

    某些安全性较高的网页,如网上支付或用户登陆页面,可能会使用到https(SSL/TLS)来提高安全性.本文介绍了如何在ASP.NET MVC中强制某action使用https和如何进行向https页面 ...

  9. SSL、TLS协议格式、HTTPS通信过程、RDP SSL通信过程(缺heartbeat)

    SSL.TLS协议格式.HTTPS通信过程.RDP SSL通信过程   相关学习资料 http://www.360doc.com/content/10/0602/08/1466362_30787868 ...

随机推荐

  1. 中文版Postman测试需要登陆才能访问的接口(基于Cookie)

    ApiPost堪称增强版的中文postman,是一个支持团队协作,并可直接生成文档的API调试.管理工具.它支持模拟POST.GET.PUT等常见请求,是后台接口开发者或前端.接口测试人员不可多得的工 ...

  2. 结对项目(JAVA)

    项目成员: 邓镇港 3117004608 陈嘉欣 3117004604 一.Github项目地址: https://github.com/kestrelcjx/operation_expression ...

  3. Java集合学习(9):集合对比

    一.HashMap与HashTable的区别 HashMap和Hashtable的比较是Java面试中的常见问题,用来考验程序员是否能够正确使用集合类以及是否可以随机应变使用多种思路解决问题.Hash ...

  4. 利用selenium和ffmpeg爬取m3u8 ts视频《进击的巨人》

    需求 想看下动漫<进击的巨人>,发现到处被和谐,找不到资源,但是在一个视频网站找到了在线播放,https://www.55cc.cc/dongman/17890/player-2-1.ht ...

  5. 机器学习之KMeans聚类

    零.学习生成测试数据 from sklearn.datasets import make_blobs from matplotlib import pyplot # create test data ...

  6. java修饰符在含义以及在eclipse下的显示

    java四类修饰符的含义: public:公开的修饰符,没有调用限制,只用有该对象的路径,都可以调用. protected:在本类,同一个包,或子类中可以被调用. default(没有修饰符):在同一 ...

  7. Android端项目测试

    目录 一.概述 二.使用工具 三.测试 1.测试主要的两大功能 进入主界面,测试排行榜查看功能是否能运行 测试83端口打卡能否运行 修改个人信息已经注册功能 2.测试参数是否正确 3.测试刷新能否使用 ...

  8. 我以为我对Kafka很了解,直到我看了此文章

    Kafka 是一个消息系统,原本开发自 LinkedIn,用作 LinkedIn 的活动流(Activity Stream)和运营数据处理管道(Pipeline)的基础. 现在它已被多家不同类型的公司 ...

  9. 重新学习Spring注解——Spring容器

    44.[源码]-Spring容器创建-BeanFactory预准备 45.[源码]-Spring容器创建-执行BeanFactoryPostProcessor 46.[源码]-Spring容器创建-注 ...

  10. Mac下Sublime Text常用插件

    Mac下Sublime Text常用插件 SideBarEnhancements 右键菜单增强插件 BracketHighlighter 括号.引号.标签高亮插件 Pretty JSON JSON美化 ...