spring security自定义决策管理器

发布时间 - 2026-01-11 03:24:09    点击率:

首先介绍下Spring的决策管理器,其接口为AccessDecisionManager,抽象类为AbstractAccessDecisionManager。而我们要自定义决策管理器的话一般是继承抽象类而不去直接实现接口。

在Spring中引入了投票器(AccessDecisionVoter)的概念,有无权限访问的最终觉得权是由投票器来决定的,最常见的投票器为RoleVoter,在RoleVoter中定义了权限的前缀,先看下Spring在RoleVoter中是怎么处理授权的。

public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) { 
  int result = ACCESS_ABSTAIN; 
  Collection<? extends GrantedAuthority> authorities = extractAuthorities(authentication); 
  for (ConfigAttribute attribute : attributes) { 
    if (this.supports(attribute)) { 
      result = ACCESS_DENIED; 
      // Attempt to find a matching granted authority 
      for (GrantedAuthority authority : authorities) { 
        if (attribute.getAttribute().equals(authority.getAuthority())) { 
          return ACCESS_GRANTED; 
        } 
      } 
    } 
  } 
  return result; 
} 
Collection<? extends GrantedAuthority> extractAuthorities(Authentication authentication) { 
  return authentication.getAuthorities(); 
} 

Authentication中是用户及用户权限信息,attributes是访问资源需要的权限,然后循环判断用户是否有访问资源需要的权限,如果有就返回ACCESS_GRANTED,通俗的说就是有权限。

Spring提供了3个决策管理器,至于这三个管理器是如何工作的请查看SpringSecurity源码

AffirmativeBased 一票通过,只要有一个投票器通过就允许访问

ConsensusBased 有一半以上投票器通过才允许访问资源

UnanimousBased 所有投票器都通过才允许访问

下面来实现一个简单的自定义决策管理器,这个决策管理器并没有使用投票器

public class DefaultAccessDecisionManager extends AbstractAccessDecisionManager { 
  public void decide( Authentication authentication, Object object,  
      Collection<ConfigAttribute> configAttributes)  
    throws AccessDeniedException, InsufficientAuthenticationException{ 
    SysUser user = (SysUser)authentication.getPrincipal(); 
    logger.info("访问资源的用户为"+user.getUsername()); 
    //如果访问资源不需要任何权限则直接通过 
    if( configAttributes == null ) { 
      return ; 
    } 
    Iterator<ConfigAttribute> ite = configAttributes.iterator(); 
    //遍历configAttributes看用户是否有访问资源的权限 
    while( ite.hasNext()){ 
      ConfigAttribute ca = ite.next(); 
      String needRole = ((SecurityConfig)ca).getAttribute(); 
      //ga 为用户所被赋予的权限。 needRole 为访问相应的资源应该具有的权限。 
      for( GrantedAuthority ga: authentication.getAuthorities()){ 
        if(needRole.trim().equals(ga.getAuthority().trim())){ 
          return; 
        } 
      } 
    } 
    throw new AccessDeniedException(""); 
  } 
} 

 decide这个方法没有任何的返回值,需要在没有通过授权时抛出AccessDeniedException。

如果有访问某个资源需要同时拥有两个或两个以上权限的情况,这时候就要通过自定义AccessDecisionVoter来实现了,这个也很简单在这里就不赘述了。如果要在页面中使用hasRole()这样的表达式就需要注入WebExpressionVoter了。
在SpringSecurity中自定义权限前缀

权限的前缀默认是ROLE_,网上的很多例子是说,直接在配置文件中加上下面的配置就可以了。

<bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter"> 
  <property name="rolePrefix" value="AUTH_"></property> 
</bean> 

亲测不管用的,我想应该不是我配置的问题,而是在我们配置了http auto-config="true"Spring就已经将AccessDecisionManager初始化好了,即便配置到之前也不行,因为这个初始化是Spring自己来完成的,它并没有把你配置的roleVoter注入到AccessDecisionManager中。那我们就来手动的注入AccessDecisionManager吧。

在http配置中有个access-decision-manager-ref属性,可以使我们手动注入AccessDecisionManager,下面是详细配置

<sec:http auto-config="true" access-decision-manager-ref="accessDecisionManager"> 
  <sec:access-denied-handler ref="accessDeniedHandler"/> 
  <sec:session-management invalid-session-url="/login.jsp" /> 
  <sec:intercept-url pattern="/app.jsp" access="AUTH_GG_FBGBGG"/> 
  <sec:intercept-url pattern="/**" access="IS_AUTHENTICATED_FULLY" /> 
  <sec:form-login login-page="/login.jsp" authentication-failure-url="/login.jsp" 
    default-target-url="/index.jsp"/> 
</sec:http> 
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased"> 
  <constructor-arg name="decisionVoters"> 
    <list> 
      <ref bean="roleVoter"/> 
      <ref bean="authenticatedVoter"/> 
    </list> 
  </constructor-arg> 
  <property name="messageSource" ref="messageSource"></property> 
</bean> 
<bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter"> 
  <property name="rolePrefix" value=""></property> 
</bean> 
<bean id="authenticatedVoter" class="org.springframework.security.access.vote.AuthenticatedVoter" /> 

在这里我们就不用自定义的AccessDecisionManager了,直接用Spring的AffirmativeBased,因为Spring本身提供的这些决策管理器就已经很强大了。

配置很简单,要想修改权限的前缀只需要修改roleVoter中的rolePrefix就可以了,如果不要前缀就让它为“”。

authenticatedVoter是为了支持IS_AUTHENTICATED这种认证,authenticatedVoter提供的3种认证,分别是

IS_AUTHENTICATED_ANONYMOUSLY 允许匿名用户进入

IS_AUTHENTICATED_FULLY 允许登录用户进入

IS_AUTHENTICATED_REMEMBERED 允许登录用户和rememberMe用户进入

总结

以上所述是小编给大家介绍的spring security自定义决策管理器,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!


# spring  # security自定义  # security决策管理器  # Spring Boot中整合Spring Security并自定义验证代码实例  # java中自定义Spring Security权限控制管理示例(实战篇)  # spring security自定义登录页面  # spring security自定义认证登录的全过程记录  # 管理器  # 自定义  # 在这里  # 小编  # 就可以  # 我想  # 好了  # 有个  # 抽象类  # 在此  # 的说  # 就不  # 是由  # 没有任何  # 是怎么  # 遍历  # 不去  # 要在  # 把你  # 也很 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 成都网站制作公司哪家好,四川省职工服务网是做什么用?  如何用AWS免费套餐快速搭建高效网站?  Laravel如何配置和使用缓存?(Redis代码示例)  Laravel软删除怎么实现_Laravel Eloquent SoftDeletes功能使用教程  使用C语言编写圣诞表白程序  浅谈redis在项目中的应用  javascript中数组(Array)对象和字符串(String)对象的常用方法总结  Laravel如何使用Gate和Policy进行权限控制_Laravel权限判定与策略规则配置  Laravel如何实现API速率限制?(Rate Limiting教程)  php增删改查怎么学_零基础入门php数据库操作必知基础【教程】  微信小程序 五星评分(包括半颗星评分)实例代码  Laravel怎么创建控制器Controller_Laravel路由绑定与控制器逻辑编写【指南】  Javascript中的事件循环是如何工作的_如何利用Javascript事件循环优化异步代码?  1688铺货到淘宝怎么操作 1688一键铺货到自己店铺详细步骤  Mybatis 中的insertOrUpdate操作  焦点电影公司作品,电影焦点结局是什么?  详解MySQL数据库的安装与密码配置  PHP 实现电台节目表的智能时间匹配与今日/明日轮播逻辑  如何快速生成可下载的建站源码工具?  Laravel如何使用Seeder填充数据_Laravel模型工厂Factory批量生成测试数据【方法】  深圳网站制作培训,深圳哪些招聘网站比较好?  Laravel与Inertia.js怎么结合_使用Laravel和Inertia构建现代单页应用  如何在阿里云香港服务器快速搭建网站?  齐河建站公司:营销型网站建设与SEO优化双核驱动策略  百度输入法ai面板怎么关 百度输入法ai面板隐藏技巧  Laravel怎么实现验证码功能_Laravel集成验证码库防止机器人注册  Laravel的契約(Contracts)是什么_深入理解Laravel Contracts与依赖倒置  深圳网站制作设计招聘,关于服装设计的流行趋势,哪里的资料比较全面?  Laravel怎么实现观察者模式Observer_Laravel模型事件监听与解耦开发【指南】  Laravel如何实现一对一模型关联?(Eloquent示例)  Windows家庭版如何开启组策略(gpedit.msc)?(安装方法)  Laravel Fortify是什么,和Jetstream有什么关系  制作旅游网站html,怎样注册旅游网站?  java获取注册ip实例  如何在Windows环境下新建FTP站点并设置权限?  阿里云高弹*务器配置方案|支持分布式架构与多节点部署  详解免费开源的.NET多类型文件解压缩组件SharpZipLib(.NET组件介绍之七)  香港服务器租用每月最低只需15元?  深圳网站制作的公司有哪些,dido官方网站?  简历没回改:利用AI润色让你的文字更专业  WEB开发之注册页面验证码倒计时代码的实现  iOS UIView常见属性方法小结  如何在IIS中新建站点并配置端口与IP地址?  Laravel怎么实现搜索高亮功能_Laravel结合Scout与Algolia全文检索【实战】  Midjourney怎样加参数调细节_Midjourney参数调整技巧【指南】  JS经典正则表达式笔试题汇总  如何实现javascript表单验证_正则表达式有哪些实用技巧  儿童网站界面设计图片,中国少年儿童教育网站-怎么去注册?  logo在线制作免费网站在线制作好吗,DW网页制作时,如何在网页标题前加上logo?  实例解析angularjs的filter过滤器