项⽬权限管理⼤纲(RBAC+SpringSecurity)
这⾥写⽬录标题
资源,权限,⾓⾊,⽤户
权限管理是为了管理⽤户⾏为,保护⽬标系统的安全,权限 = 权利 + 限制
1 资源的定义:
资源就是系统需要保护起来的功能,有url,handler⽅法,service⽅法,页⾯元素…
2 权限的定义
因为⼀个功能的完成可能涉及到成千上万的资源,如果以资源做为权限分配的基本单位那就很不痛快,我们将n个相关操作的资源封装为⼀个"权限",再将这个权限分配给有需要的⼈,这可以看出是对权限操作的简化,资源可以看成⼀个handler
3 ⾓⾊
将资源包装为权限是对资源管理的简化,⽽⽤户的数量同样不是⼩数⽬,⼀个个的管理是不现实的,我们可以将⽤户划分不同的⾓⾊,即⾓⾊就是⽤户的分类分组。资源封装为权限,权限分配给⾓⾊,再给⽤户指定⾓⾊,这也是RABC模型的⼤纲
4 ⽤户
具有系统使⽤权限和登录账号的⼀类⼈
权限 => 资源
数据库层⾯n:n,java层⾯1:n(每个权限类封装⼀个资源列表,但是资源类中不需要考虑权限这个属性,即不需要知道这个资源对应那些权限)
⾓⾊ => 权限
数据库层⾯n:n,java层⾯1:n(⾓⾊类封装⼀个权限列表,但权限类不需要考虑⾓⾊这个属性,即不需要考虑权限对应对应那些⾓⾊)
⽤户 => ⾓⾊
数据库层⾯n:n,java层⾯n:n(⽤户类封装⼀个⾓⾊列表来表⽰这个⽤户所具有的⾓⾊,也可以查看这个这个⾓⾊下的所有⽤户) RBAC
(Role-Base-Access Controller) ⽤户通过⾓⾊获得相关的权限,⼀个⽤户可以有多种⾓⾊,⼀个⾓⾊对于多种权限,⼀个权限代表⼀个功能
1 互斥⾓⾊:不能同时给⽤户分配到⼀起的⾓⾊,如会计师和审计师⾓⾊
2 约束⾓⾊:⾓⾊的访问权限和旗下的⽤户数量是受限的,⼀个⽤户拥有的⾓⾊数量也受限
先决条件就是,⾓⾊拥有A权限的条件是拥有B权限,如⽤户升到vip6级的条件是要达到vip5级
3 动态分离级别:马云在阿⾥巴巴内部激活创始⼈⾝份,在企业论坛上激活演讲嘉宾⾓⾊
数据表设计
五张基础表
⽤户(admin)表
⾓⾊表role
权限表
name命名规范如user:save,表⽰具有保存⾓⾊的权限
⽤户-⾓⾊表
⾓⾊-权限表
SpringSecurity配合RBAC补全权限验证
背景:spring ioc注解
使⽤SpringSecurity前,我们已经将auth分配给了role,将role分配给了admin,形参了⼀条完整的admin-role-auth链,之前的代码或配置的放⾏资源信息都注释掉决不能共存
基本实现步骤
1 在springsecurity的配置类中配置放⾏的资源 ,通过继承WebSecurityConfigurerAdapter然后重写co
nfigure(HttpSecurity security),这⾥⾯配置以下内容
定制放⾏资源,有登录的⾸页,退出登录,全部的静态资源img/jquery/css…,除了这些放⾏到的其它都要进⾏验证
开启form表单登录功能、指定登录的页⾯、指定处理登录请求的handler、指定登录成功后的跳转页⾯, 指定from表单的登录框和密码框的name值。注意:此时已经没有真正的登录处理handler⽅法了,有的只是在configure中进⾏的登录验证。
指定资源访问权限,例如admin主页⾯只有经理采⽤访问权限,也可以采⽤在handler⽅法上加注解的形式控制
开发阶段禁⽤csrf
搭建springsecurity独⽴的异常处理体系
开启退出登录功能、处理⽅法、退出后的跳转页⾯
配置7天内记住我功能①绑定数据源②绑定登录handler③
2 定义SecurityAdmin,这个类作为SpringSecurity权限处理后的封装结果集来使⽤,来将admin对象和该对象所具有的权限(⾓⾊+权限)绑定,绑定admin对象的username、password、authorites这三类信息,⽤户认证成功信息会被SecurityAdmin封装到principle变量并被存储在xxx类,调⽤⽗类的构造器验证登录⽤户的合法性并擦除对象密码,进⼀步提⾼安全性,这样⽅便前台打印(前端代码中不要忘记引⼊springsecurity标签库)。
3 重写configure(AuthenticationManagerBuilder builder)
可以在临时在内存中存储登录信息测试代码,项⽬初始化测试和部署到服务器上的时候必须考虑这⼀点。 易错点:如果前端引⼊了springsecurity标签库并且⽤principle进⾏了前端参数回显会产⽣报错,因为principle这个参数是从secuityAdmin中获取到的,内存帮登录信息不涉及securityAdmin
测试完毕将内存登录改装成数据库版登录测试
①定义UserDetailsService实现类,步骤如下:
注⼊adminService/RoleService/AuthService这三个对象 => 接收username(参数)=> 获取对应的admin =>取出adminId => 根据adminId获取该⾓⾊的权限集合和⾓⾊集合 => 遍历权限和⾓⾊集合(⾓⾊集合名前⾯加ROLE_来区分⾓⾊与权限)将其封装为SimpleGrantedAuthority加⼊已创建的权限列表=>将获取的admin对象及它的authorities封装为SecurityAdmin对象并返回
密码加密
1) 装配BCryptPasswordEncoder组件,configure⽅法中使⽤该组件进⾏密码加密
2)淘汰之前写的md5加密⽅法,并在之前写的保存⽤户⽅法中更换掉md5加密⽅法
4 前端
①form填写handler路径
②前端重点参数
${SPRING_SECURITY_LAST_EXCEPTION } #springsecurity前端错误信息提⽰,⽤于登录页⾯回显
<security:authentication property="iginalAdmin.userName"/> #公共区域侧边栏,显⽰已登录⽤户的名称信息
③注意,表单的⽤户名和密码⽂本框推荐⾃定义取name名,但要到配置类配置,否则springsecurity⽆法识别
④引⼊springsecurity标签库来表⽰已登录的信息
5 搭建异常处理体系
由下图可知springsecurity的异常是⽆法被springmvc的异常处理机制处理的,所以分为两部分,⼀部分是专门处理SpringMVC的dispacherServlet拦截的异常路径,另⼀部分是处理SpringSecurity拦截的
⽅法是在configure中搭建springsecurity独⽴的异常处理体系
总结:SpringSecurity中⾓⾊和权限近乎等价,也就是handler处理器所对应的资源除了和auth挂钩也可以和role挂钩,⽽且也可以将⼀份资源的访问权限设计为具有xxx⾓⾊或xxx权限,例如
.access("hasRole('经理') or hasAnyAuthority('user:get')") #具备经理或⽤户保存权限可以访问该资源的权限(管理admin信息的权限)
实现记住我功能
基本原理
具体实现⽅法
⽤户登录 => 第⼆步的登录过滤器验证 => 验证成功后相关组件⽣成Token => 该组件⼀⽅⾯将token写⼊浏览器的Cookie(cookie名就是前端checkbot的name)另⼀⽅⾯存⼊数据库中 => ⽤户下次登录时相关组件⼀⽅⾯查浏览器cookie另⼀⽅⾯去数据库(persist_login)进⾏查 =>对⽐两个值,相等则跳过springsecurity的登录验证,实现步骤如下
建⽴数据表persistent_ogin
configure端配置七天内记住我功能,绑定数据源操作组件persistentTokenRepository和⽤户登录验证组件userDetailsService,配置连接保存时长为七天
前端配置记住我的cehckbox组件,name必须是固定的
结论
数据库端⽣成
浏览器端也有相应的⽣成
再次登录主页发现不需要验证(我们的设计是将ip:port/projectName/admin/to/main/page.html作为主页,⽤户选择记住我就不需要以登录的形式进⾏springsecurity验证⽽是直接就能跳转。反正,⽤户没有实现记住我,直接进⼊主页会被springsecurity拦截,造成权限不够⽽被强制以跳转到登录页的形式进⾏springsecurity验证)
实现SpringSecurity版验证码登录
1 导⼊spring-social-config依赖
2 entity编写验证码实体类IamgeCode
private BufferedImage image;//验证码图⽚
private String code;//code验证码
private LocalDateTime expireTime;//过期时间单位秒
3 componet的mvc下编写验证码⽣成处理器ValidateCodeController
createImageCode:⼯具⽅法,⽤于⽣成ImageCode类型的验证码信息
sessionStrategy属性:使⽤sessionStrategy将⽣成的验证码对象存储到Session中
createCode:将⽣成的验证码对象存储到Session中,并通过IO流将⽣成的图⽚输出到登录页⾯上,在前端页⾯通过该⽅法的访问路径加载⽣成的图⽚,并通过点击进⾏看不清刷新
<img src="code/image.html"/>
4 在springsecurity配置configure中放⾏⽣成的验证码handler路径资源的访问
5 编写过滤器ValidateCodeFilter进⾏登录时验证码的校验
继承OncePerRequestFilter,重写doFilterInternal
doFilterInternal⽅法①如果拦截的页⾯是post请求的登录页⾯,那么就拦截下来有待进⼀步验证,其余静态资源全部放⾏②合法性验证:判断是否合法,不合法要返回相应的错误信息③验证通过后⽴即删除session中原先的验证码,防⽌影响下⼀次验证码校验将该过滤器注⼊到WebAppSecurityConfig(相当于将该过滤器组件加⼊到了springsecurity容器中)并在configure中将该过滤器的执⾏顺序配置到验证登录的过滤器前⾯
security.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class);
权限管理的使⽤
在WebAppSecurityConfig这个springsecurity配置类上使⽤注解
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论