我正在尝试使用两种方式 ssl 通过 Socket.IO 进行身份验证来启动和运行 FeatherJS 应用程序。我已经构建了一个简单的证书策略、验证器等来处理验证所呈现的用户是否是有效用户的任务。
然而——在这一点上,我尝试的一切都在循环发送给我。我发誓它似乎没有运行身份验证,当我让它最终踢出一些调试消息时,peerCert 永远不会出现。
我在这里做错了什么?
index.js
const server = https.createServer({
key: fs.readFileSync('certificates/my.key'),
cert: fs.readFileSync('certificates/my-cert.pem'),
ca: fs.readFileSync('certificates/ca/my-ca.pem'),
requestCert: true,
rejectUnauthorized: true
}, app).listen(port);
app.setup(server);
现在,当我第一次访问该站点时,我确实会收到证书提示,但是我看不到任何证据表明该证书可以进入我的身份验证服务。
应用程序.js
const feathers = require('feathers');
const configuration = require('feathers-configuration');
const hooks = require('feathers-hooks');
const socketio = require('feathers-socketio');
const handler = require('feathers-errors/handler');
const notFound = require('feathers-errors/not-found');
const middleware = require('./middleware');
const services = require('./services');
const appHooks = require('./app.hooks');
const authentication = require('./authentication');
const app = feathers();
// Load app configuration
app.configure(configuration());
// Enable CORS, security, compression, favicon and body parsing
app.use(cors());
app.use(helmet());
app.use(compress());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(favicon(path.join(app.get('public'), 'favicon.ico')));
// Host the public folder
app.use('/', feathers.static(app.get('public')));
// Set up Plugins and providers
app.configure(hooks());
app.configure(socketio());
// Configure other middleware (see `middleware/index.js`)
app.configure(middleware);
app.configure(authentication);
// Set up our services (see `services/index.js`)
app.configure(services);
// Configure a middleware for 404s and the error handler
app.use(notFound());
app.use(handler());
app.hooks(appHooks);
module.exports = app;
身份验证.js
const authentication = require('feathers-authentication');
const jwt = require('feathers-authentication-jwt');
const cert = require('./feathers-authentication-cert.js');
module.exports = function () {
const app = this;
const config = app.get('authentication');
// Set up authentication with the secret
app.configure(authentication(config));
app.configure(jwt());
app.configure(cert());
// The `authentication` service is used to create a JWT.
// The before `create` hook registers strategies that can be used
// to create a new valid JWT (e.g. local or oauth2)
app.service('authentication').hooks({
before: {
create: [authentication.hooks.authenticate(config.strategies)],
remove: [authentication.hooks.authenticate('jwt')]
}
});
};
羽毛认证-cert.js
const Debug = require('debug');
const merge = require('lodash.merge');
const omit = require('lodash.omit');
const pick = require('lodash.pick');
const DefaultVerifier = require('./cert-verifier.js');
const ClientCertStrategy = require('./cert-strategy.js').Strategy;
const debug = Debug('feathers-authentication-cert');
const defaults = {
name: 'cert'
};
const KEYS = [
'passReqToCallback',
'session'
];
function init(options = {}) {
return function certAuth() {
const app = this;
const _super = app.setup;
if (!app.passport) {
throw new Error(`Can not find app.passport. Did you initialize feathers-authentication before feathers-authentication-cert?`);
}
let name = options.name || defaults.name;
let authOptions = app.get('authentication') || {};
let localOptions = authOptions[name] || {};
const localSettings = merge({}, defaults, pick(authOptions, KEYS), localOptions, omit(options, ['Verifier']));
let Verifier = DefaultVerifier;
if (options.Verifier) {
Verifier = options.Verifier;
}
app.setup = function () {
let result = _super.apply(this, arguments);
let verifier = new Verifier(app, localSettings);
if (!verifier.verify) {
throw new Error(`Your verifier must implement a 'verify' function. It should have the same signature as a local passport verify callback.`)
}
// Register 'cert' strategy with passport
debug('Registering cert authentication strategy with options:', localSettings);
app.passport.use(localSettings.name, new ClientCertStrategy(localSettings, verifier.verify.bind(verifier)));
app.passport.options(localSettings.name, localSettings);
return result;
}
};
}
// Exposed Modules
Object.assign(init, {
defaults,
Verifier: DefaultVerifier
});
module.exports = init;
证书策略.js
const util = require('util');
const Strategy = require('passport-strategy');
/*
* passport.js TLS client certificate strategy
*/
function ClientCertStrategy(options, verify) {
if (typeof options == 'function') {
verify = options;
options = {};
}
if (!verify) throw new Error('Client cert authentication strategy requires a verify function');
Strategy.call(this);
this.name = 'client-cert';
this._verify = verify;
this._passReqToCallback = options.passReqToCallback;
}
util.inherits(ClientCertStrategy, Strategy);
ClientCertStrategy.prototype.authenticate = function(req, options) {
var that = this;
console.log('Request', req);
// Requests must be authorized
// (i.e. the certificate must be signed by at least one trusted CA)
if(!req.socket.authorized) {
that.fail();
} else {
var clientCert = req.socket.getPeerCertificate();
// The cert must exist and be non-empty
if(!clientCert || Object.getOwnPropertyNames(clientCert).length === 0) {
that.fail();
} else {
var verified = function verified(err, user) {
if (err) { return that.error(err); }
if (!user) { return that.fail(); }
that.success(user);
};
if (this._passReqToCallback) {
this._verify(req, clientCert, verified);
} else {
this._verify(clientCert, verified);
}
}
}
};
module.exports.Strategy = ClientCertStrategy;
证书验证器.js
class CertVerifier {
constructor (app, options = {}) {
this.app = app;
this.options = options;
this.verify = this.verify.bind(this);
}
verify(req, cert, done) {
console.log(req.socket);
done= () => {
console.log('done?');
}
var subject = cert.subject;
var msg = 'Attempting PKI authentication';
if(!subject) {
console.log(msg + ' ✘ - no subject'.red);
done(null, false);
} else if(!subject.CN) {
console.log(msg + '✘ - no client CN'.red);
done(null, false);
} else {
var cn = subject.CN;
lookupUser(cn, function(err, user) {
msg = 'Authenticating ' + cn + ' with certificate';
if(!user) {
console.log(msg + ' ✘ - no such user'.red);
done(null, false);
} else {
console.log(msg + ' - ✔'.green);
done(null, user);
}
});
}
}
}
module.exports = CertVerifier;