Malagu 框架的认证与授权【借鉴 Spring Security 和 aws iam 的设计】
前言
Malagu 是基于 TypeScript 的 Serverless First、可扩展和组件化的应用框架。
简介
Malagu Security 组件主要提供认证和授权相关功能。Security 借鉴了 Spring Security 和 aws 的 iam 的设计。
使用方法
Malagu 组件就是一个普通的 npm 包,可以通过以下命令安装:
安装完后,就可以直接运行了。
默认配置
实现登录页面
在登录页面中,通过 POST 请求提交用户名(username)和密码(password)到 /login ,将会触发框架的认证流程,默认提供的用户名为:admin,密码为:123456,当然,您也可以实现 UserStore 接口提供您自己用户信息。当用户名和密码都匹配成功后,则认证成功,跳转到登录成功页面,默认是 / ,否则认证失败,跳转到登录页面 /login 。
自定义 UserStore
您可以通过查询数据库获取用户信息,以下为框架默认实现,返回固定的用户信息:
方法保护
默认对外的方法都会保护起来,当您没有登录通过 ajax 直接方法,将返回 401 状态码;当您没有登录通过浏览器访问页面,将返回 302 状态码,重定向到登录页面。
登录成功后,当您有权限访问该方法,则访问成功,当您没有权限访问该方法,则访问失败,返回 403 状态码。
匿名访问
方法上添加装饰器 @Anonymous ,可以让方法可以匿名访问。
也可以添加到类上,让类的所有方法可以里面访问。
授权
任何方法或者页面都需要显示授权才能访问,单单认证通过是不够的,可以授权给用户访问某些方法的权限,也可以授权给方法,允许哪类用户可以访问。框架会更加这些权限信息做权限验证,验证通过了才可以访问具体的方法和页面,后面会做详细的展开。
认证机制
说明:
安全上下文中间件负责尝试从 Session 还原安全上下文内容
所有的请求都会到达认证管理器,认证管理器会尝试匹配认证提供,如果该 请求没有匹配到认证提供者,则忽略,继续往下执行后面的中间件
认证管理器可能匹配到多个认证提供者,只要其中存在一个是认证通过的,则表示认证通过
框架默认的认证提供者会尝试从请求参数和 body - 中获取用户名和密码,通过用户名从用户存储器中加载用户信息,用户不存在,则抛出认证异常,认证失败,如果存在,则会继续校验密码是否正确,另外还有一些其他用户状态的校验,都通过了,则认证成功
认证成功后,返回 Token,Token 中往往包含了用户基本信息,Token 会设置到安全上下文中,安全上下文中的内容会持久化到 Session 中
您可以通过实现自己认证提供者,满足自己业务特殊的认证需求
您可以通过属性配置自定义自己的登录页面地址、登录成功地址等等
密码加密采用随机盐 + 秘钥的 Pbkdf2 的哈希算法,框架提供了一个默认秘钥,真实场景记得一定要改成您自己的秘钥。当然,您也可以自定义哈希算法
认证提供者
认证管理器会将真正的认证任务委派给认证提供者,您也可以自定义认证提供者,只需要实现接口 AuthenticationProvider,并以 AuthenticationProvider 接口为 id 注入到 IoC 容器即可。
support 方法往往是匹配当前请求的路由是否为我们指定的即可。示例如下:
授权机制
说明:
授权是通过 AOP 机制实现
安全元信息包含资源、操作、授信主体、授权类型和策略
通过安全元信息可以分别获得资源权限策略和授信主体权限策略,然后更加策略类型匹配对应的策略解释器来解析策略
一般情况下,一种类型的策略对应一个策略解释器,可以根据业务需要定义自己的策略语法规则和策略解释器
策略可以所属授信主体,也是所属资源,策略可以在代码写死,也可以配置文件配置,还可以存储在数据库当中
授信主体一般是系统用户,也可以是其他逻辑上的授信主体
授权方式包括前置授权和后置授权
安全元信息
访问决策管理器基于安全元信息和策略来进行权限判断。
安全元信息下文
安全元信息源会基于安全元信息上下文获得安全元信息。
安全元信息源
基于安全元信息上下文获得安全元信息。
访问决策管理器
基于安全元信息进行访问决策。
访问决策投票器
访问决策管理器会把真正的决策任务委派给访问决策投票器。您也可以自定义认证提供者,只需要实现接口 AccessDecisionVoter,并以 AccessDecisionVoter 接口为 id 注入到 IoC 容器即可。
权限策略
策略(Policy)是对权限的描述,策略语法可以是任意形式,只要有对应的策略解释器来解释就好。策略可以分配给授信主体,也可以分配给资源。当然,也可以根据业务需要将策略分配给角色,角色可以再分配给某个用户,这样用户就拥有了角色的策略,换而言之,用户拥有了角色的权限。
云平台的策略
企业可以在云平台上创建很多资源,企业如何安全的管理这些资源,这就是云平台的策略需要考虑的问题,云平台的策略是这样来描述权限:谁在什么条件下能对哪些资源的哪些操作进行处理。
在 Malagu 框架中可以很方便地实现这样的效果,您只需要定义一个策略语法来表达:谁在什么条件下能对哪些资源的哪些操作进行处理。然后在实现一个对应的策略解释器即可。
如果您不需要定义像云平台那样复杂的策略,您完全可以更加您自己的业务需要定义您自己的策略语法。
默认策略
Malagu 框架提供给了一个默认策略:EL 表达式策略,当 EL 表达式计算结果为 true,表示允许,否则表示拒绝。用户可以在方法上通过相关的权限装饰器定义策略,也可以通过组件属性定义策略。
EL 表达式策略
Malagu 框架提供给了一个默认策略:EL 表达式策略,当 EL 表达式计算结果为 true,表示允许,否则表示拒绝。用户可以在方法上通过相关的权限装饰器配置策略,也可以通过组件属性配置策略。
定义
权限装饰器
为了用户方便地配置 EL 表达式策略,框架提供了一些列权限装饰器 @Authorize 、 @PreAuthorize 、 @PostAuthorize 、 @Anonymous 和 @Authenticated 。
其中,@PreAuthorize 、 @PostAuthorize、 @Anonymous 和 @Authenticated 是对 @Authorize 的扩展。
@Authorize
装饰器的配置属性:
@PreAuthorize
扩展 @Authorize 装饰器,等价于将 @Authorize 的 authorizeType 属性固定为前置授权。具体实现如下:
@PostAuthorize
扩展 @Authorize 装饰器,等价于将 @Authorize 的 authorizeType 属性固定为后置授权。具体实现如下:
@Anonymous
扩展 @Authorize 装饰器,等价于将 @Authorize 的 el 属性固定为 true 和 authorizeType 属性固定为前置授权 。具体实现如下:
@Authenticated
扩展 @Authorize 装饰器,等价于将 @Authorize 的 el 属性固定为 authenticated 和 authorizeType 属性固定为前置授权 。具体实现如下:
其中,authenticated 是内置的 EL 上下文变量,当为 true 时,表示当前登录用户认证通过;当为 false 时,表认证失败。
EL 表达式上下文
我们往往需要一些变量或者方法参与到 EL 表达式的计算中,框架通过 EL 表达式上下文来提供这些变量或者方法,默认提供的 EL 表达式上下文如下:
扩展 EL 表达式上下文
框架提供了一个扩展接口 SecurityExpressionContextHandler 用于扩展 EL 表达式上下文。
集中式认证与授权
Malagu 默认提供的单体式认证与授权,认证与授权过程都发生在本地应用中,如何将认证与授权进行集中式授权呢?框架设计初期就考虑这个问题。
集中式认证
我们只需要实现一个自己的认证提供者就可以了,将认证委托给远端统一认证服务即可。如果在非 Malagu 框架体系的应用,可以通过 rest 接口或者 Rpc 接口实现同样的效果。
集中式授权
我们只需要实现一个自己的认证管理器就可以了,将授权委托给远端统一授权服务务即可。如果在非 Malagu 框架体系的应用,可以通过 rest 接口或者 Rpc 接口实现同样的效果。
相关链接
版权声明: 本文为 InfoQ 作者【木香丘】的原创文章。
原文链接:【http://xie.infoq.cn/article/e6988cd73f0eb9c949ef5a94a】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论