Malagu 框架提供给了一个默认策略:EL 表达式策略,当 EL 表达式计算结果为 true,表示允许,否则表示拒绝。用户可以在方法上通过相关的权限装饰器配置策略,也可以通过组件属性配置策略。
定义
export interface Policy {type: PolicyTypeauthorizeType: AuthorizeType;}export interface ElPolicy extends Policy {context: any;el: string;}
权限装饰器
为了用户方便地配置 EL 表达式策略,框架提供了一些列权限装饰器 @Authorize 、 @PreAuthorize 、 @PostAuthorize 、 @Anonymous 和 @Authenticated 。
其中,@PreAuthorize 、 @PostAuthorize、 @Anonymous 和 @Authenticated是对 @Authorize 的扩展。
@Authorize
装饰器的配置属性:
export interface AuthorizeOption {el: string;authorizeType: AuthorizeType; // 授权类型包括前置授权和后置授权}
@PreAuthorize
扩展 @Authorize 装饰器,等价于将 @Authorize 的 authorizeType 属性固定为前置授权。具体实现如下:
export const PreAuthorize = function (el: string) {return Authorize({ el, authorizeType: AuthorizeType.Pre });};
@PostAuthorize
扩展 @Authorize 装饰器,等价于将 @Authorize 的 authorizeType 属性固定为后置授权。具体实现如下:
export const PostAuthorize = function (el: string) {return Authorize({ el, authorizeType: AuthorizeType.Post });};
@Anonymous
扩展 @Authorize 装饰器,等价于将 @Authorize 的 el 属性固定为 true 和 authorizeType 属性固定为前置授权 。具体实现如下:
export const Anonymous = function (): any {return Authorize({ el: 'true', authorizeType: AuthorizeType.Pre });};
@Authenticated
扩展 @Authorize 装饰器,等价于将 @Authorize 的 el 属性固定为 authenticated 和 authorizeType 属性固定为前置授权 。具体实现如下:
export const Authenticated = function () {return Authorize({ el: 'authenticated', authorizeType: AuthorizeType.Pre });};
其中,authenticated 是内置的 EL 上下文变量,当为 true 时,表示当前登录用户认证通过;当为 false 时,表认证失败。
EL 表达式上下文
我们往往需要一些变量或者方法参与到 EL 表达式的计算中,框架通过 EL 表达式上下文来提供这些变量或者方法,默认提供的 EL 表达式上下文如下:
export interface ElContext {authorizeType: AuthorizeTypemethod: string;args: any[];target: any;returnValue?: any;policies: Policy[];credentials: any;details?: any;principal: any;authenticated: boolean;}
扩展 EL 表达式上下文
框架提供了一个扩展接口 SecurityExpressionContextHandler 用于扩展 EL 表达式上下文。
定义
export interface SecurityExpressionContextHandler {handle(context: any): Promise<void>}
实现
@Component(SecurityExpressionContextHandler)export class SecurityExpressionContextHandlerImpl implements SecurityExpressionContextHandler {handle(context: any): Promise<void> {context.foo = 'bar';context.hasRole = () => { ... };}}
