如何让 Node.Js 允许我为客户端证书提供智能卡/cac
Posted
技术标签:
【中文标题】如何让 Node.Js 允许我为客户端证书提供智能卡/cac【英文标题】:How to get Node.Js to allow me to provide client cert with smart card/cac 【发布时间】:2021-08-02 10:10:26 【问题描述】:我正在尝试使用 node.js 构建 CAC 身份验证系统,但遇到了问题。我遵循了一些关于设置 https 服务器的教程,我可以让它正常工作;但是,每当我访问我的服务器时,使用下面的逻辑:
https://localhost:3000
系统提示我使用“/”路由处理程序发送的身份验证按钮登录;但是,它立即默认为 else 子句:
res.status(401)
.send(`Sorry, but you need to provide a client certificate to continue.`)
通常,当访问启用 cac 的站点时,会提示我选择一个智能卡证书,它允许我登录;但是,在这种情况下,我根本没有收到提示。
我找到了similar question on SO,但无法从他们引用的文章中得到任何工作。他们提到我必须在 https 服务器上设置我的“ca”属性以允许相关 CAC 的特定 CA。我使用浏览器找到了我的 CAC 证书并导出了我的证书并将它们放入已批准的 CA 列表中,但我仍然没有收到任何提示。
我最初使用req.connection.getPeerCertificate()
来提示输入证书;但是,我读到 req.connection 在我的 Node.JS (14.15.0) 版本中已被弃用,所以我也尝试了req.socket.getPeerCertificate()
。无论哪种方式,服务器似乎都运行得很好,我在客户端或服务器端都没有错误(除了从服务器发送的 401 响应,因为它没有获得有效的证书)。任何和所有的见解将不胜感激。
const fs = require('fs')
const express = require('express')
const https = require('https')
// Https options
const options =
// Path to private key (created by openssl in createSelfSignedCert.bat)
key: fs.readFileSync('server_key.pem')
// Path to public key
,cert: fs.readFileSync('server_cert.pem')
// Indicate that https server should request client certificates
,requestCert: true
// Manually handle bad requests (no certs)
,rejectUnauthorized: false
//List of accepted/valid CA certs - just our own for now
,ca: [
fs.readFileSync('server_cert.pem')
,fs.readFileSync('cac52.cer')
,fs.readFileSync('cac_export.p7b')
]
//,ca: .
// Use express for routing
const app = express()
// Unprotected public endpoint
app.get('/', (req, res) =>
res.send('<a href="login">Auth</a>')
)
// Protected endpoint
app.get('/login', (req, res) =>
// req.connection is deprecated, perhaps req.socket.getPeerCertificate()
const cert = req.connection.getPeerCertificate()
//const cert = req.socket.getPeerCertificate()
if (req.client.authorized)
res.send(`Hello $cert.subject.CN, your certificate was issued by $cert.issuer.CN!`)
console.log(`$cert`)
else if (cert.subject)
res.status(403)
.send(`Sorry $cert.subject.CN, certificates from $cert.issuer.CN are not welcome here.`)
console.log(`$cert`)
else
res.status(401)
.send(`Sorry, but you need to provide a client certificate to continue.`)
)
// Create https server with options and app routes
https.createServer(options, app).listen(3000)
【问题讨论】:
【参考方案1】:我通过在浏览器 (Chrome) 中更改此设置来实现此功能:
chrome://flags/#allow-insecure-localhost
我是从this answer 那里得到的。我认为 Chrome 并没有提示我选择证书,因为它将我的开发环境视为不安全。启用该设置后,证书提示按预期出现,“/login” URL 显示我选择的证书的 CN。
此外,您还需要确保您拥有正确的 CA。 AFAIK,您不能只从 CAC 导出 CA 证书链 - 您需要从 CA 向您提供它们。如果您正在从事 DoD 项目,您将需要 DoD 根 CA。如果您已经拥有 DoD CAC,则可以从 this link 获取 DoD 根 CA。
请记住,您的 CAC 上加载的证书是客户端证书,它们对您来说是唯一的。 CA(认证机构)是向您颁发这些证书的组织。当您将 CA 证书添加到您的项目时,您的应用实际上是在说“我可以接受此 CA 颁发的客户端证书。”
【讨论】:
以上是关于如何让 Node.Js 允许我为客户端证书提供智能卡/cac的主要内容,如果未能解决你的问题,请参考以下文章
无论证书有效性如何,我的 node.js https 客户端始终有效
使用 node.js 验证带有 CA 证书的 X509 证书