RBAC:基于角色的访问控制(Role-Based Access Control)

先在web.xml 中配置一个过滤器(必须在Struts的过滤器之前)

  1. <filter>
  2. <filter-name>springSecurityFilterChain</filter-name>
  3. <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  4. </filter>
  5. <filter-mapping>
  6. <filter-name>springSecurityFilterChain</filter-name>
  7. <url-pattern>/*</url-pattern>
  8. </filter-mapping>

然后就是编写Spring安全的配置文件applicationContext-security.xml并配置到Spring解析的路径下

Spring Security主要做两件事,一件是认证,一件是授权。

认证

当用户访问受保护的信息却没有登录获得认证时,框架会自动将请求跳转到登录页面

在http标签中的

  1. <form-login login-page="/page/login.jsp" />

配置。且该登录页面必须是不被拦截的。故要配置上

  1. <intercept-url pattern="/page/login.jsp" filters="none" />

Web项目的认证如果在HTTP标签中配置了auto-config="true",框架就会自动的配置多8?个拦截器。
默认表单登录认证的是FORM_LOGIN_FILTER拦截器,我们可以直接写自定义的UserDetailsService,在这个类中实现方法
UserDetails loadUserByUsername(String username),从数据库获取用户信息,以及其拥有的角色。

  1. @Service("myUserDetailsService")
  2. public class MyUserDetailsServiceImpl extends BaseService implements UserDetailsService {
  3. @Resource
  4. private UserDao userDao;
  5. public UserDetails loadUserByUsername(String username)
  6. throws UsernameNotFoundException, DataAccessException {
  7. User user = userDao.getUserByUsername(username);
  8. List<Role> roles = user.getRoles();
  9. Collection<GrantedAuthority> authorities = new LinkedList<GrantedAuthority>();
  10. for (Role role : roles) {
  11. authorities.add(new GrantedAuthorityImpl(role.getCode()));
  12. }
  13. UserDetails userDetails = new org.springframework.security.core.userdetails.User(username,user.getPassword(),Constants.STATE_VALID.equals(user.getState()),true,true,true,authorities);
  14. return userDetails;
  15. }
  16. }

配置在

  1. <authentication-manager alias="myAuthenticationManager">
  2. <authentication-provider user-service-ref="myUserDetailsService">
  3. <password-encoder hash="md5" />
  4. </authentication-provider>
  5. </authentication-manager>

如果需要在登录的时候,在HTTP SESSION中配置做些操作的。就得配置自定义的FORM_LOGIN_FILTER了

在HTTP标签中加入

  1. <custom-filter ref="loginFilter" before="FORM_LOGIN_FILTER" />

并配置

  1. <!-- 访问控制验证器Authority -->
  2. <beans:bean id="securityFilter"
  3. class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
  4. <beans:property name="authenticationManager" ref="myAuthenticationManager" />
  5. <beans:property name="accessDecisionManager"
  6. ref="affirmativeBasedAccessDecisionManager" />
  7. <beans:property name="securityMetadataSource" ref="mySecurityMetadataSource"/>
  8. </beans:bean>

MyUsernamePasswordAuthenticationFilter 类是这么写的

  1. public class MyUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter{
  2. public static final String USERNAME = "username";
  3. public static final String PASSWORD = "password";
  4. @Resource
  5. private LoginService loginService;
  6. private UserLoginFormBean userLoginFormBean = new UserLoginFormBean();
  7. @Resource
  8. private LogService logService;
  9. @Override
  10. public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
  11. String username = obtainUsername(request);
  12. String password = obtainPassword(request);
  13. HttpSession session = request.getSession();
  14. userLoginFormBean.setUsername(obtainUsername(request));
  15. userLoginFormBean.setPassword(obtainPassword(request));
  16. User user = loginService.login(userLoginFormBean);
  17. session.setAttribute(Constants.SESSION_USER, user);
  18. Log log = new Log(user,getIpAddr(request),"用户登录", null);
  19. logService.add(log);
  20. //UsernamePasswordAuthenticationToken实现 Authentication
  21. UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
  22. // Place the last username attempted into HttpSession for views
  23. // 允许子类设置详细属性
  24. setDetails(request, authRequest);
  25. // 运行UserDetailsService的loadUserByUsername 再次封装Authentication
  26. return this.getAuthenticationManager().authenticate(authRequest);
  27. }
  28. }

getAuthenticationManager().authenticate(authRequest)是为了让UserDetailService提供Detailed的信息并认证

授权

在授权时,系统默认通过FILTER_SECURITY_INTERCEPTOR认证。

如需自定义授权拦截器,我们在HTTP中在默认授权拦截器前配置了自定义的拦截器

  1. <custom-filter ref="securityFilter" before="FILTER_SECURITY_INTERCEPTOR" />

本平台采用基于请求URL地址的验证方式

securityFilter的配置如下

  1. <!-- 访问控制验证器Authority -->
  2. <beans:bean id="securityFilter"
  3. class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
  4. <beans:property name="authenticationManager" ref="myAuthenticationManager" />
  5. <beans:property name="accessDecisionManager"
  6. ref="affirmativeBasedAccessDecisionManager" />
  7. <beans:property name="securityMetadataSource" ref="mySecurityMetadataSource"/>
  8. </beans:bean>

采用默认的自定义的也是采用Spring默认的FilterSecurityInterceptor拦截器,accessDecisionManager也采用的是框架提供的affirmativeBasedAccessDecisionManager
采用投票者来判断是否授权。

  1. <beans:bean id="affirmativeBasedAccessDecisionManager"
  2. class="org.springframework.security.access.vote.AffirmativeBased">
  3. <beans:property name="decisionVoters" ref="roleDecisionVoter" />
  4. </beans:bean>
  5. <beans:bean name="roleDecisionVoter"
  6. class="org.springframework.security.access.vote.RoleVoter" />
  7. <beans:bean id="mySecurityMetadataSource"
  8. class="org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource">
  9. <beans:constructor-arg
  10. type="org.springframework.security.web.util.UrlMatcher" ref="antUrlPathMatcher" />
  11. <beans:constructor-arg type="java.util.LinkedHashMap"
  12. ref="securityRequestMapFactoryBean" />
  13. </beans:bean>

SecurityMetadataSource也是ss
web框架提供的DefaultFilterInvocationSecurityMetadataSource,只是初始化参数中,一个选择
antUrl匹配,还是正则匹配,另一个是提供自定义的通过securityRequestMapFactoryBean。在后者是一个
LinkedHashMap<RequestKey,
Collection<ConfigAttribute>>类型,就是每一个URL匹配模式,所需要角色的集合。

  1. @Service("securityRequestMapFactoryBean")
  2. public class SecurityRequestMapFactoryBean extends
  3. LinkedHashMap<RequestKey, Collection<ConfigAttribute>> {
  4. @Resource
  5. private ModuleDao moduleDao;
  6. @PostConstruct
  7. public void loadSecurityInfos(){
  8. List<Module> modules = moduleDao.getAll(new Module());
  9. //      List<Role> roles = roleDao.getAll(new Role());
  10. for (Module module : modules) {
  11. RequestKey requestKey = new RequestKey(module.getPageUrl());
  12. Collection<ConfigAttribute> configAttributes = new LinkedList<ConfigAttribute>();
  13. for (final Role role : module.getRoles()) {
  14. configAttributes.add(new ConfigAttribute() {
  15. public String getAttribute() {
  16. return role.getCode();
  17. }
  18. });
  19. }
  20. this.put(requestKey, configAttributes);
  21. }
  22. }
  23. }

PS: 最终的件applicationContext-security.xml配置文件

    1. <pre name="code" class="html"><?xml version="1.0" encoding="UTF-8"?>
    2. <beans:beans xmlns="http://www.springframework.org/schema/security"
    3. xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    5. http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
    6. <http auto-config="true">
    7. <intercept-url pattern="/page/login.jsp" filters="none" />
    8. <intercept-url pattern="/LoginAction*" filters="none" />
    9. <intercept-url pattern="/common/**" filters="none" />
    10. <intercept-url pattern="/css/**" filters="none" />
    11. <intercept-url pattern="/common/**" filters="none" />
    12. <intercept-url pattern="/images/**" filters="none" />
    13. <intercept-url pattern="/js/**" filters="none" />
    14. <form-login login-page="/page/login.jsp" />
    15. <custom-filter ref="loginFilter" before="FORM_LOGIN_FILTER" />
    16. <custom-filter ref="securityFilter" before="FILTER_SECURITY_INTERCEPTOR" />
    17. </http>
    18. <!-- 访问控制验证器Authority -->
    19. <beans:bean id="securityFilter"
    20. class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
    21. <beans:property name="authenticationManager" ref="myAuthenticationManager" />
    22. <beans:property name="accessDecisionManager"
    23. ref="affirmativeBasedAccessDecisionManager" />
    24. <beans:property name="securityMetadataSource" ref="mySecurityMetadataSource"/>
    25. </beans:bean>
    26. <!-- 登录验证器Authentication -->
    27. <beans:bean id="loginFilter"
    28. class="com.epro.crm.util.security.MyUsernamePasswordAuthenticationFilter">
    29. <!-- 处理登录的action -->
    30. <beans:property name="filterProcessesUrl" value="/SecurityCheck" />
    31. <!-- 验证成功后的处理-->
    32. <beans:property name="authenticationSuccessHandler"
    33. ref="loginLogAuthenticationSuccessHandler" />
    34. <!-- 验证失败后的处理-->
    35. <beans:property name="authenticationFailureHandler"
    36. ref="simpleUrlAuthenticationFailureHandler" />
    37. <beans:property name="authenticationManager" ref="myAuthenticationManager" />
    38. <!-- 注入DAO为了查询相应的用户 -->
    39. <beans:property name="loginService" ref="loginService" />
    40. <beans:property name="logService" ref="logService" />
    41. </beans:bean>
    42. <authentication-manager alias="myAuthenticationManager">
    43. <authentication-provider user-service-ref="myUserDetailsService">
    44. <password-encoder hash="md5" />
    45. </authentication-provider>
    46. </authentication-manager>
    47. <beans:bean id="mySecurityMetadataSource"
    48. class="org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource">
    49. <beans:constructor-arg
    50. type="org.springframework.security.web.util.UrlMatcher" ref="antUrlPathMatcher" />
    51. <beans:constructor-arg type="java.util.LinkedHashMap"
    52. ref="securityRequestMapFactoryBean" />
    53. </beans:bean>
    54. <beans:bean id="antUrlPathMatcher"
    55. class="org.springframework.security.web.util.AntUrlPathMatcher" />
    56. <beans:bean id="affirmativeBasedAccessDecisionManager"
    57. class="org.springframework.security.access.vote.AffirmativeBased">
    58. <beans:property name="decisionVoters" ref="roleDecisionVoter" />
    59. </beans:bean>
    60. <beans:bean name="roleDecisionVoter"
    61. class="org.springframework.security.access.vote.RoleVoter" />
    62. <beans:bean id="loginLogAuthenticationSuccessHandler"
    63. class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
    64. <beans:property name="defaultTargetUrl" value="/page/main.jsp"></beans:property>
    65. </beans:bean>
    66. <beans:bean id="simpleUrlAuthenticationFailureHandler"
    67. class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
    68. <!--
    69. 可以配置相应的跳转方式。属性forwardToDestination为true采用forward false为sendRedirect
    70. -->
    71. <beans:property name="defaultFailureUrl" value="/page/login.jsp"></beans:property>
    72. </beans:bean>
    73. <!-- 未登录的切入点 -->
    74. <beans:bean id="authenticationProcessingFilterEntryPoint"
    75. class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
    76. <beans:property name="loginFormUrl" value="/page/login.jsp"></beans:property>
    77. </beans:bean>
    78. </beans:beans></pre><br>
    79. ------------------------------------------------------ 分割线 -----------------------------------------------------------------<br>
    80. <br>
    81. 后记:
    82. <pre></pre>
    83. 由于权限配置信息,是由初始化mySecurityMetadataSource时,就由mySecurityMetadataSource读取提供的权限信息,并缓存与该类的私有成员变量中,所以重新加载时就需要重新新建一个对象
    84. <pre></pre>
    85. <pre name="code" class="java">public void loadSecurityInfos(){
    86. this.clear();
    87. List<Module> modules = moduleDao.getAll(new Module());
    88. Collections.sort(modules);
    89. for (Module module : modules) {
    90. RequestKey requestKey = new RequestKey(module.getPageUrl());
    91. Collection<ConfigAttribute> configAttributes = new LinkedList<ConfigAttribute>();
    92. moduleDao.refresh(module);
    93. List<Role> roles = module.getRoles();
    94. if(roles != null){
    95. for (final Role role : roles) {
    96. configAttributes.add(new ConfigAttribute() {
    97. public String getAttribute() {
    98. return role.getCode();
    99. }
    100. });
    101. }
    102. }
    103. this.put(requestKey, configAttributes);
    104. log.info(module.getName()+ "模块 URL模式:" + requestKey + " 授权角色:"+ roles);
    105. }
    106. }</pre><br>
    107. <br>
    108. <pre></pre>
    109. <pre></pre>
    110. <pre></pre>
    111. <pre></pre>
    112. <pre></pre>
    113. <pre></pre>
    114. <pre></pre>
    115. <pre></pre>
    116. <pre></pre>
    117. <pre></pre>
    118. <pre></pre>
    119. <div style="padding-top:20px">
    120. <p style="font-size:12px;">版权声明:本文为博主原创文章,未经博主允许不得转载。</p>
    121. </div>

[转]Spring Security 可动态授权RBAC权限模块实践的更多相关文章

  1. spring security实现动态配置url权限的两种方法

    缘起 标准的RABC, 权限需要支持动态配置,spring security默认是在代码里约定好权限,真实的业务场景通常需要可以支持动态配置角色访问权限,即在运行时去配置url对应的访问角色. 基于s ...

  2. Spring Security之动态配置资源权限

    在Spring Security中实现通过数据库动态配置url资源权限,需要通过配置验证过滤器来实现资源权限的加载.验证.系统启动时,到数据库加载系统资源权限列表,当有请求访问时,通过对比系统资源权限 ...

  3. Spring Security 解析(一) —— 授权过程

    Spring Security 解析(一) -- 授权过程   在学习Spring Cloud 时,遇到了授权服务oauth 相关内容时,总是一知半解,因此决定先把Spring Security .S ...

  4. spring security中动态更新用户的权限

    在程序的执行过程中,有时有这么一种需求,需要动态的更新某些角色的权限或某些人对应的权限,当前在线的用户拥有这个角色或拥有这个权限时,在不退出系统的情况下,需要动态的改变的他所拥有的权限. 需求:张三 ...

  5. 基于Spring Security 的JSaaS应用的权限管理

    1. 概述 权限管理,一般指根据系统设置的安全规则或者安全策略,用户可以访问而且只能访问自己被授权的资源.资源包括访问的页面,访问的数据等,这在传统的应用系统中比较常见.本文介绍的则是基于Saas系统 ...

  6. Spring security 用户,角色,权限,资源

    转自:http://blog.csdn.net/wybqq/article/details/52940194 关于Spring security对用户请求的处理过程 体现在这两个过程的体现. 关于用户 ...

  7. spring-security-4 (4)spring security 认证和授权原理

    在上一节我们讨论了spring security过滤器的创建和注册原理.请记住springSecurityFilterChain(类型为FilterChainProxy)是实际起作用的过滤器链,Del ...

  8. spring boot系列--spring security (基于数据库)登录和权限控制

    先说一下AuthConfig.java Spring Security的主要配置文件之一 AuthConfig 1 @Configuration 2 @EnableWebSecurity 3 publ ...

  9. spring boot:spring security实现oauth2授权认证(spring boot 2.3.3)

    一,oauth2的用途? 1,什么是oauth2? OAuth2 是一个开放标准, 它允许用户让第三方应用访问该用户在某一网站上存储的私密资源(如头像.照片.视频等), 在这个过程中无须将用户名和密码 ...

随机推荐

  1. Java垃圾收集算法

    算法名称 过程 优缺点 1. 标记-清除算法 (Mark-Sweep) 分为两个阶段: 1.首先标记出所有需要回收的对象: 2.在标记完成后统一回收所有被标记的对象. 缺点: 1.效率问题:标记和清除 ...

  2. USB 3.1 與 USB Type-C 解釋

    https://tw.transcend-info.com/Support/FAQ-940 以下的內容皆來自上面這個網址. 什麼是USB 3.1? 什麼是USB 3.1? USB 3.1為USB協會制 ...

  3. Linux内核死锁检测机制【转】

    转自:http://www.oenhan.com/kernel-deadlock-check 死锁就是多个进程(线程)因为等待别的进程已占有的自己所需要的资源而陷入阻塞的一种状态,死锁状态一旦形成,进 ...

  4. (转)关于bootstrap, boosting, bagging,Rand forest

    转自:https://blog.csdn.net/jlei_apple/article/details/8168856 这两天在看关于boosting算法时,看到一篇不错的文章讲bootstrap, ...

  5. keil问题:Error: failed to execute 'C:\Keil\ARM\BIN\ArmCC'

    1.打开cmd,进入相应的路径下 cd C:\Keil\ARM\BIN\ 输入 armcc  若显示如下界面则说明keil已经注册 2.若注册成功还没解决问题,则说明软件是在网上下载的破解版的,建议卸 ...

  6. [转载]NGINX原理分析 之 SLAB分配机制

    作者:邹祁峰 邮箱:Qifeng.zou.job@hotmail.com 博客:http://blog.csdn.net/qifengzou 日期:2013.09.15 23:19 转载请注明来自&q ...

  7. qtp录制时间控件不允许用户手动输入的解决办法

    qtp录制时间控件不允许用户手动输入的解决办法 [前面的话] 一边学习qtp,一边用自己的项目试着写代码,而遇到一个问题就会让自己卡壳很久,这次也是这样的,在写好了登录代码以后,自己就试着写第一个预订 ...

  8. [loj#2566][BZOJ5333] [Sdoi2018]荣誉称号 树形dp

    #2566. 「SDOI2018」荣誉称号   休闲游戏玩家小 Q 不仅在算法竞赛方面取得了优异的成绩,还在一款收集钻石的游戏中排名很高. 这款游戏一共有 n 种不同类别的钻石,编号依次为 1 到 n ...

  9. Flexigrid-Web2.0 jQuery

    一.参考资料 1.jQuery插件flexiGrid的完全使用,附代码下载 2.修改flexigrid源码一(json,checkbox)[原创] 3.jQuery +UI + flexigrid做的 ...

  10. CentOS 7.4 下安装 Nginx

    CentOS 7.4 下安装 Nginx 安装所需环境 Nginx 是 C语言 开发,建议在 Linux 上运行,当然,也可以安装 Windows 版本,本篇则使用 CentOS 7 作为安装环境. ...