
Security News
Axios Supply Chain Attack Reaches OpenAI macOS Signing Pipeline, Forces Certificate Rotation
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.
express-security
Advanced tools
一套Express中间件,轻量,用于根据当前用户是否登陆、及其拥有的角色来拦截请求。
目前使用AuthenticationInterceptor、 AuthorizationInterceptor、AuthInterceptor 类作为对外统一接口。三个类的职责为:
AuthenticationInterceptor: 负责认证检查AuthorizationInterceptor:负责授权检查AuthInterceptor:负责认证和授权检查,只是以上两个类的包装AuthenticationInterceptor、AuthorizationInterceptor、或者AuthInterceptor拦截器默认的实现是基于session机制:
req.session 的可用性。req.session.username实现的。如果要定制,需要自行提供登陆检查器。req.session.roles实现的。如果要定制,需要自行提供角色访问器。所以,这时候往往需要安装第三方模块保证session可用,比如使用express-session中间件:
> npm install express-session --save
使用之前需要实例化出一个对象:
// initialize a authentication-interceptor
const authenInterceptor=new AuthenticationInterceptor();
// initialize a authorization-interceptor
const authorInterceptor=new AuthorizationInterceptor();
// or just initialize a auth-interceptor
const interceptor=new AuthInterceptor();
尽管默认的配置是基于session的,但是,AuthInterceptor、AuthenticationInterceptor、和AuthorizationInterceptor的检查机制并不和 session 耦合在一起。 通过提供自定义登陆检查器、角色访问器,完全可以丢掉 session 。
登陆检查器:函数对象,接收请求req参数,同步返回(或者以等价的异步的方式“返回”)当前用户是否登陆的boolean值,角色访问器: 函数对象,接收请求req参数,同步返回(或者以等价的异步的方式“返回”)当前用户所拥有的角色列表。放心,拦截器只会对“返回”的角色列表读操作。可以通过AuthenticationInterceptor、AuthorizationInterceptor实现自定义:
// 认证拦截器
const authenticationInterceptor=new AuthenticationInterceptor(
(req)=>{return !!req.session.username;}, // 覆盖默认的登陆检查器
);
// 授权拦截器
const authorizationInterceptor=new AuthorizationInterceptor(
(req)=>{return req.session.roles;} // 覆盖默认的角色访问器
);
// 如果你认证/授权都需要的话:
const authInterceptor=new AuthInterceptor(
(req)=>{return !!req.session.username;}, // 覆盖默认的登陆检查器
(req)=>{return req.session.roles;} // 覆盖默认的角色访问器
);
当前,还可以提供msg对象作为附加的默认返回消息(详见代码实现),但是大多情况下,不需要定制此参数。
除了上面演示的同步式的登陆检查器和角色访问器,还可以使用异步式进行定制:
// 支持各类异步方式:比如可以以Promise的方式进行检查
const authenticationInterceptor=new AuthenticationInterceptor(
// 覆盖默认的登陆检查器
(req)=>{
return new Promise(function(resolve,reject){
resolve(!!req.session.username);
});
}
);
// 支持各类异步方式:还可以以callback的方式进行检查
const authorizationInterceptor=new AuthorizationInterceptor(
// 覆盖默认的角色访问器
(req,callback)=>{
setTimeout(function() {
callback(null,req.session.rolelist);
}, 100);
}
);
const interceptor=new AuthInterceptor(
(req)=>{return !!req.session.username;},
(req)=>{
return new Promise(function(resolve,reject){
resolve(req.session.rolelist);
});
}
);
除此之外,requireTrue()方法也支持使用异步式进行拦截:
const interceptor=new AuthorizationInterceptor();
interceptor.requireTrue(function(req){
return Promise.resolve(req.sth);
});
AuthenticationInterceptor和AuthorizationInterceptor实例对请求的拦截是利用express中间件原理实现的。
拦截器实例对象有一系列requireXxx()方法,比如
requireLogin()requireRole()requireAnyRole()requireAllRoles()requireTrue()AuthInterceptor的requireXxx()只是简单调用AuthenticationInterceptor和AuthorizationInterceptor的相应requireXxx()方法。
每个这种方法都是一个高阶函数,调用后会返回一个中间件函数,用于拦截请求:
// 要求拥有 "ROLE_ROOT" 角色,否则提示失败消息然后重定向到根目录"/"
router.use("/admin",interceptor.requireRole("ROLE_ROOT","/"));
通过npm安装:
> npm install express-security --save
测试:
> npm run test
可以根据需要,分别实例化一个AuthenticationInterceptor和AuthorizationInterceptor。
const express=require('express');
const {AuthInterceptor,AuthenticationInterceptor,AuthorizationInterceptor}=require('express-security');
const router=express.Router();
const authenInterceptor=new AuthencationInterceptor(
(req)=>{return !!req.session.username;},
);
const interceptor=new AuthorizationInterceptor(
(req)=>{return req.session.roles;}
);
// 要求登陆
router.use('/dashboard',authenInterceptor.requireLogin());
// 要求登陆,自定义重定向页面
router.use('/user/detail',authenInterceptor.requireLogin("/account"));
// 要求拥有 "ROLE_ADMIN" 角色
router.use("/admin",interceptor.requireRole("ROLE_ADMIN","/"));
// 要求拥有 "ROLE_ROOT"、"ROLE_ADMIN" 中任意一个角色
router.use("/sudo",interceptor.requireAnyRole(["ROLE_ROOT","ROLE_ADMIN"]));
// 要求拥有 "ROLE_0"、"ROLE_1"、"ROLE_2" 中全部角色
router.use("/holy",interceptor.requireAllRoles(["ROLE_0","ROLE_1","ROLE_2"]));
// 要求返回正确值的可调用对象
router.use("/shit",interceptor.requireTrue((req)=>{return !! req.query.sth;},"/"));
如果同时需要根据用户登录状态和角色信息对请求进行拦截,也可以直接实例化一个AuthInterceptor作为统一的外部接口。
const AuthInterceptor=new AuthInterceptor(
(req)=>{return !!req.session.username;},
(req)=>{return req.session.roles;}
);
参见我的这篇笔记:ASP.NET 与 Node.js 的协作实践
FAQs
lightweight authentication/authorization express middleware
We found that express-security demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.

Security News
Open source is under attack because of how much value it creates. It has been the foundation of every major software innovation for the last three decades. This is not the time to walk away from it.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.