如何在NodeJS中自定义keycloak错误消息

问题描述

我是节点上的新手,我有一个带有express的rest api,并且某些端点使用keycloak-connect具有keycloak安全性。当发生错误403时,我需要一个自定义响应,即json格式的自定义消息。我使用处理程序来管理其他一些状态,例如200、201、204、404、500,但是当密钥斗篷抛出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'),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,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}`);
});

解决方法

问题是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
,

您可以在初始化之前覆盖 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'),res) {
  res.json({message: 'admin'});
});

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

// Error Handler
app.use((err,req,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}`);
});

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...