HapiJs 基于角色路由访问

HapiJs routes access base on role

我在服务器端使用HapiJs,想做基于角色的路由配置,我想限制用户访问一些端点

var Hapi = require('hapi');

var server = new Hapi.Server();
server.connection({ port: 8000 });

server.route({
  method: 'GET',
  path: 'api1',
  handler: function (request, reply) {
    reply('Hello, world!');
  }
});

server.route({
  method: 'GET',
  path: 'api2',
  handler: function (request, reply) {
    reply('Hello');
  }
});

server.route({
  method: 'GET',
  path: 'api3',
  handler: function (request, reply) {
    reply('Hello');
  }
});

const parseHeader = (request, h) => {
   const { role } = JSON.parse(request.headers["roles"]);

};

server.ext("onRequest", parseHeader);

server.start(function () {
  console.log('Server running at:', server.info.uri);
});

在这里,我从角色 header 中获取角色,因此角色可以是 "admin" 或 "customer"。如果角色是管理员用户可以访问所有 api 端点 'api1'、'api2' 和 'api3' 但如果其 "customer" 则只能访问 'api3' .

如何实现路由的这种授权?

您需要创建 "middleware" - 将检查用户角色的预处理程序, 如果用户的角色是 admin ,则继续,否则拒绝访问

var Boom = require('boom');


const CheckAdmin= function (request, reply) {
    const { role } = JSON.parse(request.headers["roles"]);
    if(role=='admin'){
       return reply.continue();
    }else{
       return reply(Boom.unauthorized('Access Denied'));
    }
}



 server.route({
    method: 'GET',
    path: 'api1',
    config: {
         pre: [{ method: CheckAdmin }],
         handler: function (request, reply) {
         reply('Hello, world!');
    }
  });

server.route({
  method: 'GET',
  path: 'api2',
  config: {
         pre: [{ method: CheckAdmin }],
         handler: function (request, reply) {
         reply('Hello, world!');
    }
});

// api3 是开放的,都可以使用,所以这里不需要添加前置处理器

server.route({
  method: 'GET',
  path: 'api3',
  handler: function (request, reply) {
    reply('Hello');
  }
});

hapi.js 有一个默认机制。它被称为 auth scope

使用范围字段定义路由的身份验证配置

exports.userList = {
    description: 'list users',
    auth: {
        scope: ['admin]
    },    
    handler: async (request, h) => {
        // .. your code here
    }
};

也就是说,只有管理员范围内的用户可以访问此路由。

然后在您的身份验证代码中将范围字段添加到您的凭据对象。

exports.plugin = {
    async register(server, options) {
        const implementation = function (server, options) {

            return {
                authenticate: function (request, h) {

                    // check user here
                    const user = findInDbOrSomething();
                    if (!user) {                        
                        // redirect user to login page
                        return h.redirect('/auth/login').takeover()
                    }

                    credentials = {
                        name: user.name,
                        email: user.email,
                        scope: ["admin"] // or user.scope if user has a scope field or get it from somewhere else
                    }

                    return h.authenticated({credentials});
                }
            }
        };
        server.auth.scheme('basic', implementation);
        server.auth.strategy('simple', 'basic');
        server.auth.default('simple')
    },
    name: 'auth',
    version: require('../package.json').version
};