2

我正在尝试使用两种方式 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;
4

0 回答 0