自签名证书客户端身份验证与本地主机上的客户端和服务器
Self sign certificate client authentication with client and server both on localhost
我在 localhost:9002 上有一个 node/express 服务器 运行ning https,我想将客户端证书用于 React 应用程序,运行ning 在 [=104] =](webpack 开发服务器)。 React 应用程序使用 ajax 向 https 服务器发送超级代理请求,我有一个护照中间件来自动检查证书。
环境
Windows10,Chrome版本71.0.3578.98
设置
我使用 openssl 创建了一个根 CA。然后我生成了我的服务器证书和客户端证书。这是使用的脚本(我 运行 它与 git bash,所以它是 UNIX 风格,但我在 windows 上):
## CREATE CERTIFICATES FOR AUTHENTICATION
#########################################
## 1. Create Root Certificate Authority #
#########################################
# Root CA private key
openssl genrsa -out ./rootCA.key 4096
# Root CA certificate to register in RootCA store on OS
openssl req -x509 -new -nodes -key ./rootCA.key -sha256 -days 3650 -out ./rootCA.pem
#################################
## 2. Create Server certificate #
#################################
# Create private key for server
openssl genrsa -out ./server.key 4096
# Create server certificate sign request (CSR) based on the private key
openssl req -new -sha256 -nodes -out ./server.csr -key ./server.key -config ./server.csr.conf
# Create server certificate linked to the previoulsy created Root CA
openssl x509 -req -in ./server.csr -CA ./rootCA.pem -CAkey ./rootCA.key -CAcreateserial -out ./server.crt -days 3650 -sha256 -extfile ./v3.ext
#################################
## 3. Create Client certificate #
#################################
# Create private key for client
openssl genrsa -out ./client.key 4096
# Create the Certificate Sign Request (CSR) file from the client private key
openssl req -new -config ./client.csr.conf -key ./client.key -out ./client.csr
# Self sign the certificate for 10 years
openssl x509 -req -days 3650 -in ./client.csr -CA ./server.crt -CAkey ./server.key -CAcreateserial -out ./client.crt
# Display the fingerprint of the newly generated fingerprint
openssl x509 -noout -fingerprint -inform pem -in ./client.crt
# Generate a PFX file for integration in browser
openssl pkcs12 -export -out ./client.pfx -inkey ./client.key -in ./client.crt -passout pass:
以下是使用的不同配置:
server.csr.conf
[ req ]
default_bits = 4096
default_md = sha512
prompt = no
encrypt_key = no
distinguished_name = req_distinguished_name
# distinguished_name
[ req_distinguished_name ]
countryName = "FR"
localityName = "Lille"
organizationName = "Sopra Steria"
organizationalUnitName = "Webskillz"
commonName = "localhost"
v3.ext
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
client.csr.conf
[ req ]
default_bits = 4096
default_md = sha512
default_keyfile = server.key
prompt = no
encrypt_key = no
distinguished_name = req_distinguished_name
# distinguished_name
[ req_distinguished_name ]
countryName = "FR"
localityName = "Lille"
organizationName = "Sopra Steria"
organizationalUnitName = "Webskillz"
commonName = "localhost"
最后,我使用 certmgr.msc 添加 rootCA.pem 到 Trusted Root Certification Authorities,并添加了 client.pfx 和 server.crt 证书到 个人 商店。
第 1 期
Chrome烦人的重定向http://localhost:8080 to https://localhost:8080,我不想系统地打开chrome://net-internals/#hsts
删除localhost键...
第 2 期
当我最终访问http://localhost:8080, I'm asked to choose the certificate I want to authenticate to https://localhost:9002时(是的!),但我仍然得到401,这不是由passport cert-auth中间件引起的(我的中间件中没有登录)。
附加信息
1。几乎可以正常工作的设置
我设法使这个 client/server 设置在没有根证书的情况下工作,但问题是我从 Chrome 获得了 NET::ERR_CERT_AUTHORITY_INVALID
...这就是我添加根证书的原因CA,按照万维网上的一些建议......确实它纠正了问题,但后来我无法进行身份验证,并且 Chrome 开始自动将 http 重定向到 https ಠ෴ಠ
哦,顺便说一句,服务器端允许 CORS,所以 CORS 没有问题。
2。服务器代码
护照验证策略:我们只是检查数据库中的指纹。
cert-auth.js
import { Strategy } from 'passport-client-cert';
export default new Strategy(async (clientCert, done) => {
console.log(clientCert); // NO LOG HERE!!
if (clientCert.fingerprint) {
try {
const user = await findByFingerprintInMyAwesomeDb({ fingerprint: clientCert.fingerprint });
return done(null, user);
} catch (err) {
return done(new Error(err));
}
}
return done(null, false);
});
bootstrap-express.js
import passport from 'passport';
import certificateStrategy from 'cert-auth';
export default (app) => {
// CORS setup, bodyparser stuff & all...
// ... //
// Using authentication based on certificate
passport.use(certificateStrategy);
app.use(passport.initialize());
app.use(passport.authenticate('client-cert', { session: false }));
// Api routes.
app.get('/api/stream',
passport.authenticate('client-cert', { session: false }),
(req, res) => {
// Some router stuff
});
};
index.js
import https from 'https';
import express from 'express';
import fs from 'fs';
import path from 'path';
import bootstrapExpress from 'bootstrap-express';
const certDir = path.join(__dirname, '..', 'cert');
const listenPromise = server => port => new Promise((resolve, reject) => {
const listener = server.listen(port, err => (err ? reject(err) : resolve(listener)));
});
const options = {
key: fs.readFileSync(path.join(certDir, 'server.key')),
cert: fs.readFileSync(path.join(certDir, 'server.crt')),
ca: fs.readFileSync(path.join(certDir, 'server.crt')),
requestCert: true,
rejectUnauthorized: false,
};
(async function main() {
try {
logger.info('Initializing server');
const app = express();
bootstrapExpress(app);
const httpsServer = https.createServer(options, app);
const httpsListener = await listenPromise(httpsServer)(9002);
logger.info(`HTTPS listening on port ${httpsListener.address().port} in ${app.get('env')} environment`);
} catch (err) {
logger.error(err);
process.exit(1);
}
}());
结论
欢迎任何帮助:)
此致
好吧,我做了很多更改,以便证书链可以更清晰,但我努力之后仍然有 401 的原因是因为我的快速服务器中的配置:
const options = {
key: fs.readFileSync(path.join(certDir, 'server.key')),
cert: fs.readFileSync(path.join(certDir, 'server.crt')),
ca: fs.readFileSync(path.join(certDir, 'server.crt')),
requestCert: true,
rejectUnauthorized: false,
};
工作配置如下(用 rootCA 替换 ca):
const options = {
key: fs.readFileSync(path.join(certDir, 'server.key')),
cert: fs.readFileSync(path.join(certDir, 'server.crt')),
ca: fs.readFileSync(path.join(certDir, 'rootCA.pem')),
requestCert: true,
rejectUnauthorized: false,
};
这个问题顺便帮助了我,但我几分钟前才找到它:https://github.com/nodejs/help/issues/253^
附加信息:为了避免从 http 重定向到 https,因为我的服务器在本地主机 DNS 上,我只是在 C:\Windows\System32\drivers\etc\host
中添加了一个新的 DNS
127.0.0.1 mysuperdns
因此,服务器证书的通用名称必须是 mysuperdns
。
我在 localhost:9002 上有一个 node/express 服务器 运行ning https,我想将客户端证书用于 React 应用程序,运行ning 在 [=104] =](webpack 开发服务器)。 React 应用程序使用 ajax 向 https 服务器发送超级代理请求,我有一个护照中间件来自动检查证书。
环境
Windows10,Chrome版本71.0.3578.98
设置
我使用 openssl 创建了一个根 CA。然后我生成了我的服务器证书和客户端证书。这是使用的脚本(我 运行 它与 git bash,所以它是 UNIX 风格,但我在 windows 上):
## CREATE CERTIFICATES FOR AUTHENTICATION
#########################################
## 1. Create Root Certificate Authority #
#########################################
# Root CA private key
openssl genrsa -out ./rootCA.key 4096
# Root CA certificate to register in RootCA store on OS
openssl req -x509 -new -nodes -key ./rootCA.key -sha256 -days 3650 -out ./rootCA.pem
#################################
## 2. Create Server certificate #
#################################
# Create private key for server
openssl genrsa -out ./server.key 4096
# Create server certificate sign request (CSR) based on the private key
openssl req -new -sha256 -nodes -out ./server.csr -key ./server.key -config ./server.csr.conf
# Create server certificate linked to the previoulsy created Root CA
openssl x509 -req -in ./server.csr -CA ./rootCA.pem -CAkey ./rootCA.key -CAcreateserial -out ./server.crt -days 3650 -sha256 -extfile ./v3.ext
#################################
## 3. Create Client certificate #
#################################
# Create private key for client
openssl genrsa -out ./client.key 4096
# Create the Certificate Sign Request (CSR) file from the client private key
openssl req -new -config ./client.csr.conf -key ./client.key -out ./client.csr
# Self sign the certificate for 10 years
openssl x509 -req -days 3650 -in ./client.csr -CA ./server.crt -CAkey ./server.key -CAcreateserial -out ./client.crt
# Display the fingerprint of the newly generated fingerprint
openssl x509 -noout -fingerprint -inform pem -in ./client.crt
# Generate a PFX file for integration in browser
openssl pkcs12 -export -out ./client.pfx -inkey ./client.key -in ./client.crt -passout pass:
以下是使用的不同配置:
server.csr.conf
[ req ]
default_bits = 4096
default_md = sha512
prompt = no
encrypt_key = no
distinguished_name = req_distinguished_name
# distinguished_name
[ req_distinguished_name ]
countryName = "FR"
localityName = "Lille"
organizationName = "Sopra Steria"
organizationalUnitName = "Webskillz"
commonName = "localhost"
v3.ext
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
client.csr.conf
[ req ]
default_bits = 4096
default_md = sha512
default_keyfile = server.key
prompt = no
encrypt_key = no
distinguished_name = req_distinguished_name
# distinguished_name
[ req_distinguished_name ]
countryName = "FR"
localityName = "Lille"
organizationName = "Sopra Steria"
organizationalUnitName = "Webskillz"
commonName = "localhost"
最后,我使用 certmgr.msc 添加 rootCA.pem 到 Trusted Root Certification Authorities,并添加了 client.pfx 和 server.crt 证书到 个人 商店。
第 1 期
Chrome烦人的重定向http://localhost:8080 to https://localhost:8080,我不想系统地打开chrome://net-internals/#hsts
删除localhost键...
第 2 期
当我最终访问http://localhost:8080, I'm asked to choose the certificate I want to authenticate to https://localhost:9002时(是的!),但我仍然得到401,这不是由passport cert-auth中间件引起的(我的中间件中没有登录)。
附加信息
1。几乎可以正常工作的设置
我设法使这个 client/server 设置在没有根证书的情况下工作,但问题是我从 Chrome 获得了 NET::ERR_CERT_AUTHORITY_INVALID
...这就是我添加根证书的原因CA,按照万维网上的一些建议......确实它纠正了问题,但后来我无法进行身份验证,并且 Chrome 开始自动将 http 重定向到 https ಠ෴ಠ
哦,顺便说一句,服务器端允许 CORS,所以 CORS 没有问题。
2。服务器代码
护照验证策略:我们只是检查数据库中的指纹。
cert-auth.js
import { Strategy } from 'passport-client-cert';
export default new Strategy(async (clientCert, done) => {
console.log(clientCert); // NO LOG HERE!!
if (clientCert.fingerprint) {
try {
const user = await findByFingerprintInMyAwesomeDb({ fingerprint: clientCert.fingerprint });
return done(null, user);
} catch (err) {
return done(new Error(err));
}
}
return done(null, false);
});
bootstrap-express.js
import passport from 'passport';
import certificateStrategy from 'cert-auth';
export default (app) => {
// CORS setup, bodyparser stuff & all...
// ... //
// Using authentication based on certificate
passport.use(certificateStrategy);
app.use(passport.initialize());
app.use(passport.authenticate('client-cert', { session: false }));
// Api routes.
app.get('/api/stream',
passport.authenticate('client-cert', { session: false }),
(req, res) => {
// Some router stuff
});
};
index.js
import https from 'https';
import express from 'express';
import fs from 'fs';
import path from 'path';
import bootstrapExpress from 'bootstrap-express';
const certDir = path.join(__dirname, '..', 'cert');
const listenPromise = server => port => new Promise((resolve, reject) => {
const listener = server.listen(port, err => (err ? reject(err) : resolve(listener)));
});
const options = {
key: fs.readFileSync(path.join(certDir, 'server.key')),
cert: fs.readFileSync(path.join(certDir, 'server.crt')),
ca: fs.readFileSync(path.join(certDir, 'server.crt')),
requestCert: true,
rejectUnauthorized: false,
};
(async function main() {
try {
logger.info('Initializing server');
const app = express();
bootstrapExpress(app);
const httpsServer = https.createServer(options, app);
const httpsListener = await listenPromise(httpsServer)(9002);
logger.info(`HTTPS listening on port ${httpsListener.address().port} in ${app.get('env')} environment`);
} catch (err) {
logger.error(err);
process.exit(1);
}
}());
结论
欢迎任何帮助:)
此致
好吧,我做了很多更改,以便证书链可以更清晰,但我努力之后仍然有 401 的原因是因为我的快速服务器中的配置:
const options = {
key: fs.readFileSync(path.join(certDir, 'server.key')),
cert: fs.readFileSync(path.join(certDir, 'server.crt')),
ca: fs.readFileSync(path.join(certDir, 'server.crt')),
requestCert: true,
rejectUnauthorized: false,
};
工作配置如下(用 rootCA 替换 ca):
const options = {
key: fs.readFileSync(path.join(certDir, 'server.key')),
cert: fs.readFileSync(path.join(certDir, 'server.crt')),
ca: fs.readFileSync(path.join(certDir, 'rootCA.pem')),
requestCert: true,
rejectUnauthorized: false,
};
这个问题顺便帮助了我,但我几分钟前才找到它:https://github.com/nodejs/help/issues/253^
附加信息:为了避免从 http 重定向到 https,因为我的服务器在本地主机 DNS 上,我只是在 C:\Windows\System32\drivers\etc\host
中添加了一个新的 DNS127.0.0.1 mysuperdns
因此,服务器证书的通用名称必须是 mysuperdns
。