无法将Keycloak与Sails集成。能够将Keycloak与Express集成

时间:2017-08-01 09:58:00

标签: node.js sails.js keycloak sails-mongo

Keycloak是一个用Java编写的开源认证和身份管理解决方案。它提供了一个nodejs适配器,使用它我可以成功地与express集成。这是有效的路线文件:

    'use strict';

module.exports = function(app) {
    var Keycloak = require('keycloak-connect');
    var session = require('express-session');


    var memoryStore = new session.MemoryStore();

    app.use(session({
          secret: 'mySecret',
          resave: false,
          saveUninitialized: true,
          store: memoryStore
    }));

    var keycloak = new Keycloak({
          store: memoryStore
    });
    app.use(keycloak.middleware({
          logout: '/logout',
          admin: '/'
    }));


    // var lRController = require('../controllers/LRController');
    //
    // app.route('/lrs').get(lRController.list_all_lrs).post(lRController.create_a_lr);


    var DeliveryOrderController = require('../controllers/DeliveryOrderController');
    app.route('/').get(keycloak.protect(), DeliveryOrderController.getAllDos)
    app.route('/api/dos').get(keycloak.protect(), DeliveryOrderController.getAllDos).post(DeliveryOrderController.createDo);
    app.route('/api/do').put(DeliveryOrderController.updateDo);
    app.route('/api/do/:doNumber').get(DeliveryOrderController.getDoByDoNumber);
    app.route('/api/do/location/:locationId').get(DeliveryOrderController.getDoByLocation);
    app.route('/api/do/branch/:branchId').get(DeliveryOrderController.getDoByBranch);
    app.route('/api/do').delete(DeliveryOrderController.deleteDo);


    var TransportDeliveryOrderController = require('../controllers/TransportDeliveryOrderController');

    app.route('/api/tdos').get(TransportDeliveryOrderController.getAllTdos).post(TransportDeliveryOrderController.createTdo);
    app.route('/api/tdo').put(TransportDeliveryOrderController.updateTdo);
    app.route('/api/tdo/:tdoNumber').get(TransportDeliveryOrderController.getTdoByTdoNumber);
    app.route('/api/tdo/status/:status').get(TransportDeliveryOrderController.getTdoByStatus);
    app.route('/api/tdo/status/:status/do/:doNumber').get(TransportDeliveryOrderController.getTdoByStatusAndDo);

};

正如您在交货单路线中所看到的,我有两条路线(同一路线的副本)受keycloak.protect()保护。我试图在帆中做同样的事情。我这样做有以下问题。

一个。要将keycloak集成到express中,需要做以下事情以保护路由

  1. 需要Keycloak并表达会话:

    var Keycloak = require('keycloak-connect'); var session = require('express-session');

  2. 定义用于存储会话的内存存储:

    var memoryStore = new session.MemoryStore();

  3. 将会话作为快捷

    中的中间件包含在内

    app.use(session({ secret: 'mySecret', resave: false, saveUninitialized: true, store: memoryStore }));

  4. 发起Keycloak:

    var keycloak = new Keycloak({ store: memoryStore });

  5. 将keycloak中间件包含在快速中间件中:

    app.use(keycloak.middleware({ logout: '/logout', admin: '/' }));

  6. 使用keycloak.protect()

    保护路线

    app.route('/api/dos').get(keycloak.protect(),DeliveryOrderController.getAllDos).post(DeliveryOrderController.createDo);

  7. 我需要在帆中建立类似的步骤。我如何在帆中做这些事情?

    我假设http.js是我添加中间件的地方。如果我这样做,如何访问routes.js中的keycloak来使用keycloak.protect()。

    例如,我可以通过以下方式添加保护功能:

    '/foo': [
     keycloak.protect(),
      { controller: 'user', action: 'find' }
    ]
    

    这是keycloak的nodejs适配器 - https://github.com/keycloak/keycloak-nodejs-connect

2 个答案:

答案 0 :(得分:2)

我终于找到了答案。 问题是keycloak.middleware()返回一个函数列表,app.use()对此感到满意。 Sails获取http.middleware列表并添加到它并在结果列表中调用app.use。如果你只包含keycloak.middleware(),你就有一个包含一系列函数的函数列表。 Express忽略了数组,因为它不是函数。

您需要将列表扩展为单独的功能。在http顶部创建一个keycloak对象并初始化它。 然后把它放在config / http.js文件的底部:

function expandList() {
    var newOrder = [];
    for (let i in module.exports.http.middleware.order)
    {
        var label = module.exports.http.middleware.order[i];
        var functor = module.exports.http.middleware[label];
        if (functor && functor.constructor === Array) {
            for (let j in functor) {
                let newlabel = label + "." + j;
                newOrder.push(newlabel);
                module.exports.http.middleware[newlabel] = functor[j];
            }
        } else {
            newOrder.push(label);
        }
    };
    module.exports.http.middleware.order = newOrder;
    return "";
}
var result = init();

在http.middleware对象中,您需要使用: keycloakMiddleware:keycloak.middleware(), 并将其添加到订单数组。

还要添加一个呼叫保护策略,并将其包括在内:

var kc = sails.config.http.keycloak.protect();
return kc(req, resp, next);

希望如果你仍然需要解决这个问题,这会有所帮助。

在调用Express

之前,也许Sails应该接受一个数组并展开它

答案 1 :(得分:1)

以上答案不适用于Sails 1.0。现在,它要求中间件是一个函数,而不是一个数组,并且keycloak从keycloak.middleware返回一个数组。 这似乎是可行的: 创建服务:KeycloakService

var session = require('express-session');
var Keycloak = require('keycloak-connect');

var memoryStore = new session.MemoryStore();
var KeycloakConfig = {
  "realm": "somerealm,
  "auth-server-url" : "https://server.com/auth",
  "resource" : "someresource,
};

module.exports = {
		config: KeycloakConfig,
		setConfig: function (config) {
			return new Keycloak({ store: memoryStore }, config);
		}
}

现在在http.js中将以下内容放在顶部

var KeycloakService = require('../api/services/KeycloakService');
var masterKeycloak = setupKeycloak();
var kcMiddleware = masterKeycloak.middleware();

function setupKeycloak() {
	if (KeycloakService.keycloak == null) {
		var config = Object.assign({}, KeycloakService.config);
		config.bearerOnly = true;
		KeycloakService.keycloak = KeycloakService.setConfig(config);
	}
	return KeycloakService.keycloak;
}

function recurseCallFunction(arr, i, req, res, next) {
  if (arr.length > i) {
    arr[i](req, res, () => recurseCallFunction(arr, i+1, req, res, next));
  } else {
    next();
  }
}

然后在middleware.order数组中包含“ keycloakMiddleware”,并在order数组下方使用

'keycloakMiddleware': function (req, res, next) {recurseCallFunction(kcMiddleware, 0, req, res, next);}
您还需要定义sails.config.http.keycloak:masterKeycloak

这将提供一个函数,该函数递归调用Keycloak中的middles函数。 您将需要定义一个策略。该政策可以做到:

  var keycloak = sails.config.http.keycloak;
  if (!req.hostname) {
    req.hostname = req.host;
  }
  var authWithKeycloak = keycloak.protect();
  if (authWithKeycloak) {
	authWithKeycloak(req, res, next);
  } else {
	sails.log.warn('Keycloak authentication could not obtain a protection checker. Contact Developers');
  }

此技术应有助于Keycloak Policy Enforcer。您可以添加到配置中以启用这些配置,并根据带有keycloak.protect的文档使用它们。我对执法者一无所知,所以我对此无能为力。