想要自定义ExpressionInterceptURL来动态管理对URL的访问

时间:2018-04-30 02:10:57

标签: spring-security

我们在需要用户访问权限的网址上提供信息包,其布局如下:

  • / InfoPacks / InfoPack1 /
  • / InfoPacks / InfoPack2 /

用户需要ROLE_INFOPACK1才能访问/ InfoPacks / InfoPack1 /和ROLE_INFOPACK2以访问/ InfoPacks / InfoPack2 /等。

我们一直在添加包,所以要添加WebSecurityConfig()                    .antMatchers(" / InfoPacks / InfoPack1 / ** / *&#34)。hasAuthority(" ROLE_INFOPACK1)  在安全配置中的配置方法变得越来越大的同时,每次创建新包时都会意味着修改和重新部署。

自定义评估器会更好。例如,可以调用服务的东西 像:

hasPermission(Authentication auth, String targetURL) {
 // search auth.GrantAuthorities for a match to targetURL
}

我看到这种与PreAuthorize一起使用的自定义权限表达式示例,但似乎没有办法使用URL authorizeRequests()。 (至少在版本4中)。

任何指示都会非常受欢迎。

1 个答案:

答案 0 :(得分:0)

得知它,感谢http://www.baeldung.com/spring-security-custom-voter。 我的网络安全配置现在看起来像:

        protected void configure(HttpSecurity http) throws Exception {
        http
                .headers()

                .frameOptions().sameOrigin()
                .and()
                .csrf().disable()
                .exceptionHandling()
                .and()
                .authorizeRequests()
                     ....
                .antMatchers("/Infopacks/**/*").authenticated().accessDecisionManager(accessDecisionManager())
                   ..... etc
}


    @SuppressWarnings("unchecked")
    @Bean
    public AccessDecisionManager accessDecisionManager() {

        System.out.println("Arrive AccessDecisionManager");

        List<AccessDecisionVoter<? extends Object>> decisionVoters 
        = Arrays.asList(
            new WebExpressionVoter(),
            new RoleVoter(),
            new AuthenticatedVoter(),
            new DynamicVoter());

        return new UnanimousBased(decisionVoters);
   }

DynamicVoter的投票方法看起来(丑陋的第一次测试 - 我知道它需要插孔工作),如:

    @Override
public int vote(Authentication a, Object s, Collection clctn) {
    String url = ((FilterInvocation) s).getRequestUrl();
    int vote = ACCESS_ABSTAIN;
    if (url.contains("/Infopack")) {
        vote = ACCESS_DENIED;
        for (GrantedAuthority ga:a.getAuthorities()) {
          if (url.toUpperCase().contains(ga.getAuthority()) ) {
            vote = ACCESS_GRANTED;
            break;
          }
        }
    }
    return vote;
}

因此,用户授权系统只需将infopack名称添加为允许用户访问infopack目录的授权权限。您可以随意添加新的infopack目录,而无需更改代码。