【问题标题】:How can custom keycloak error message in NodeJS如何在 NodeJS 中自定义 keycloak 错误消息
【发布时间】:2020-12-04 14:46:34
【问题描述】:

我是 node 上的新手,我有一个带有 express 的 rest api,一些端点使用 keycloak-connect 具有 keycloak 安全性。发生错误 403 时,我需要自定义响应,即 json 格式的自定义消息。我使用处理程序来管理其他一些状态,例如 200、201、204、404、500,但是当 keycloak 抛出 403 时我无法工作。

var memoryStore = new session.MemoryStore();

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

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

app.use(keycloak.middleware());

// keycloak security
app.get('/service/secured', keycloak.protect('realm:user'), function (req, res) {
  res.json({message: 'secured'});
});

app.get('/service/admin', keycloak.protect('realm:admin'), function (req, res) {
  res.json({message: 'admin'});
});

// 404 handler and pass to error handler
app.use((req, res, next) => {    
    next(createError(404, 'Not found'));
});

// Error Handler
app.use((err, req, res, next) => { 
    // This log never is printed when 403 ocurrs
    console.log('Error: ', err); 
    res.status(err.status || 500);
    res.send({
        error : {
            status : err.status || 500,
            message : err.message
        }
    });
});

const PORT = process.env.PORT || 3000;

app.listen(PORT, () => {
    console.log(`Server starter on port ${PORT}`);
});

【问题讨论】:

    标签: node.js keycloak keycloak-rest-api


    【解决方案1】:

    问题是 keycloak-connect 使用 express 中间件错误。它使用res.end() 而不是next(),所以在此之后你什么也做不了。您可以尝试通过添加新的中间件来重写此逻辑。

    ...
    
    app.use(function(req, res, next) {
      res.end = function(body) {
        if (res.statusCode === 403 && body === 'Access denied') {
          next(body);
        } else {
          res.send(body);
        }
      }
    });
    
    app.use(keycloak.middleware());
    
    ...
    
    // handle error how you want
    

    【讨论】:

    • 请求刚刚超时。如何返回自定义响应对象而不是默认的 Access denied 文本
    • @odane-brissett 你有路由器错误处理程序吗? expressjs.com/en/guide/error-handling.html 像这样:app.use(function (err, req, res, next) { console.error(err.stack); res.status(500).send('Something broke!'); });
    【解决方案2】:

    您可以在初始化之前覆盖 Keycloak.prototype.accessDenied 并抛出新的错误,以便您的句柄可以处理。

    var memoryStore = new session.MemoryStore();
    
    app.use(session({
      secret: 'my-secret',
      resave: false,
      saveUninitialized: true,
      store: memoryStore
    }));
    
    // Overriding keycloak access denied to return 401 status code and custom message.
    Keycloak.prototype.accessDenied = () => {
      // Considering createError will throw new Error.
      createError(401, 'Access Denied');
    };
    
    var keycloak = new Keycloak({
      store: memoryStore
    });
    
    app.use(keycloak.middleware());
    
    // keycloak security
    app.get('/service/secured', keycloak.protect('realm:user'), function (req, res) {
      res.json({message: 'secured'});
    });
    
    app.get('/service/admin', keycloak.protect('realm:admin'), function (req, res) {
      res.json({message: 'admin'});
    });
    
    // 404 handler and pass to error handler
    app.use((req, res, next) => {    
        next(createError(404, 'Not found'));
    });
    
    // Error Handler
    app.use((err, req, res, next) => { 
        // Now this print with error 401 and message Access Denied
        console.log('Error: ', err); 
        res.status(err.status || 500);
        res.send({
            error : {
                status : err.status || 500,
                message : err.message
            }
        });
    });
    
    const PORT = process.env.PORT || 3000;
    
    app.listen(PORT, () => {
        console.log(`Server starter on port ${PORT}`);
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-11
      • 1970-01-01
      • 2020-12-05
      • 1970-01-01
      • 2018-08-08
      • 2015-09-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多