V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
dzdh
V2EX  ›  Java

Java 中如何实现动态生成证书,像 Go 那样。

  •  
  •   dzdh · 2023-01-04 22:14:01 +08:00 · 2130 次点击
    这是一个创建于 722 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如 go

    func main() {
    
    	ln, _ := tls.Listen("tcp", ":433", &tls.Config{
    		GetCertificate: func(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
    			// 使用 info.ServerName 从 DB 或者临时生成
    			cert := generateX509Certificate(info.ServerName)
    			return cert, nil
    		},
    	})
    
    	http.ServeTLS(ln, nil, "", "")
    
    }
    

    Java 有类似的机制吗。哪怕是并发请求,也可以控制只有一个请求触发生成证书,其他请求 hold 住,等证书一旦生成成功,所有请求立刻进行接下来的握手(超时的不算)

    Java 中不同的框架处理方式一样吗?

    比如 javax.net.ssl.SSLContext 和使用 netty 的 spring 全家桶都适用的方法?

    14 条回复    2023-01-06 15:17:17 +08:00
    jeesk
        1
    jeesk  
       2023-01-04 22:55:16 +08:00
    gomobile ,jni . 当然你可以自己用 java 重写。
    jeesk
        2
    jeesk  
       2023-01-04 22:57:11 +08:00
    mkcert 项目,直接编译指定的平台就行了,如果是 java 自己直接使用 jni ,android,ios 都能用 gomobile.
    passer9527
        3
    passer9527  
       2023-01-04 23:27:26 +08:00
    有,我做过
    pierswu
        4
    pierswu  
       2023-01-05 10:10:39 +08:00
    你是想做证书续签吗?

    java 项目可以不用管 ssl 证书的事情,交由 nginx 去配置 ssl 。
    在使用 Certbot 或同类型的工具做证书自动续签,甚至可以自己写脚本去做续签或者生成新的证书
    dzdh
        5
    dzdh  
    OP
       2023-01-05 10:21:14 +08:00
    @pierswu

    场景是网关。可以 [随时] 新增、移除域名绑定。api.corp.com / openapi.corp.cn / api2.internal.corp.com 等等。根据当前域名去 pki 中心拿证书返回给客户端。go 实现这个很简单。java 咋搞捏。
    dzdh
        6
    dzdh  
    OP
       2023-01-05 10:23:03 +08:00
    @pierswu

    甚至还有些域名可能是需要通过自己做 ca 验证客户端证书。
    dzdh
        7
    dzdh  
    OP
       2023-01-05 10:24:23 +08:00
    @dzdh #6 网关后台有个开关,点击开,立刻所有该域名后续的 tls 握手就必须是能要求强制客户端证书验证。点击关,就立刻该域名后续的所有 tls 握手时必须不验证客户端证书。
    cnhongwei
        8
    cnhongwei  
       2023-01-05 14:45:04 +08:00
    1. JAVA 生成证书是没有问题的,就算 JCE 不行,bouncycastle 第三方包也可以,但感觉你的需求是 web 服务器能动态的更新客户端验证证书。这个感觉比较麻烦,现在就 Tomcat 和 netty 等服务器,你可以看看有没有 API 去动态更新证书的。
    2. 你的需求比较奇怪,因为客户端去服务器拿到证书,再和服务器使用新证书,这个过程没有任何安全性,和客户端发 token ,再验证 token 没有什么区别。
    3. 还有一种办法是用 nginx 处理 ssl,修改 nginx 的 ssl 配置,再重新加载 nginx 就行了。
    pierswu
        9
    pierswu  
       2023-01-05 16:41:35 +08:00
    你可以参考这个文章试试
    https://www.jianshu.com/p/62304d71c6bf
    https://www.jianshu.com/p/642c0670c0bf
    不同的 web 容器,方法是不一样的

    我同意 8 楼的第三条,建议还是用 nginx 去管理 ssl ,需要动证书的时候重新加载 nginx 就行了。
    dzdh
        10
    dzdh  
    OP
       2023-01-05 21:45:31 +08:00
    @cnhongwei #8
    @pierswu #9

    在不引入第三方组件( nginx 类)的情况下。纯 java 做不到吗?假设。我现在做一个 CDN 服务器,每个终端节点不就是要从中央仓库拿证书吗?再比如如果是 SM2 国密证书的场景,我需要判断客户端支持 SM 算法我就在本次握手时返回 SM 证书,否则返回 RSA 证书给客户端进行后续的握手操作。

    像 Go 就只需要一个 tls 的 GetCertificate 就可以了。java 实现不了吗?

    最近刚开始接触 java 。所以有点迷惑。我理解的这些语言不是都会把整个网络协议中的每一步操作都会封装成接口暴露出接口么。
    pierswu
        11
    pierswu  
       2023-01-06 10:18:58 +08:00   ❤️ 1
    我明白你的意思了,但是我没接触过这种需求。
    如果你使用的是 spring boot 框架的话,可以试着从 org.springframework.boot.web.server.SslStoreProvider 这个接口入手。
    cnhongwei
        12
    cnhongwei  
       2023-01-06 12:04:55 +08:00
    如果 cdn 的话,理论上 SNI 过程的时候,你可以自动去获取并返回动态证书。netty 中有 SniHandler,我感觉从这里扩展是可以实现的。tomcat 8.5 以上支持 SNI ,但感觉扩展没有 netty 那么方便。
    dzdh
        13
    dzdh  
    OP
       2023-01-06 15:14:40 +08:00
    @pierswu #11
    @cnhongwei #12

    佬们是通过什么渠道或方法知道有这个东西的呢?换句话说,就是咋学的呢?
    cnhongwei
        14
    cnhongwei  
       2023-01-06 15:17:17 +08:00
    google
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1787 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 16:26 · PVG 00:26 · LAX 08:26 · JFK 11:26
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.