Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/383.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在Spring Security-DenyAllPermissionEvaluator中始终拒绝访问_Java_Spring_Spring Boot_Spring Security_Acl - Fatal编程技术网

Java 在Spring Security-DenyAllPermissionEvaluator中始终拒绝访问

Java 在Spring Security-DenyAllPermissionEvaluator中始终拒绝访问,java,spring,spring-boot,spring-security,acl,Java,Spring,Spring Boot,Spring Security,Acl,我已经在Spring Boot应用程序中配置了ACL。ACL配置如下所示: @Configuration @ComponentScan(basePackages = "com.company") @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) public class ACLConfigration extends GlobalMethodSecurityConfiguration {

我已经在Spring Boot应用程序中配置了ACL。ACL配置如下所示:

@Configuration
@ComponentScan(basePackages = "com.company")
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class ACLConfigration extends GlobalMethodSecurityConfiguration {

    @Autowired
    DataSource dataSource;

    @Bean
    public EhCacheBasedAclCache aclCache() {
        return new EhCacheBasedAclCache(aclEhCacheFactoryBean().getObject(), permissionGrantingStrategy(), aclAuthorizationStrategy());
    }

    @Bean
    public EhCacheFactoryBean aclEhCacheFactoryBean() {
        EhCacheFactoryBean ehCacheFactoryBean = new EhCacheFactoryBean();
        ehCacheFactoryBean.setCacheManager(aclCacheManager().getObject());
        ehCacheFactoryBean.setCacheName("aclCache");
        return ehCacheFactoryBean;
    }

    @Bean
    public EhCacheManagerFactoryBean aclCacheManager() {
        return new EhCacheManagerFactoryBean();
    }

    @Bean
    public DefaultPermissionGrantingStrategy permissionGrantingStrategy() {
        ConsoleAuditLogger consoleAuditLogger = new ConsoleAuditLogger();
        return new DefaultPermissionGrantingStrategy(consoleAuditLogger);
    }

    @Bean
    public AclAuthorizationStrategy aclAuthorizationStrategy() {
        return new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_ACL_ADMIN"));
    }

    @Bean
    public LookupStrategy lookupStrategy() {
        return new BasicLookupStrategy(dataSource, aclCache(), aclAuthorizationStrategy(), new ConsoleAuditLogger());
    }

    @Bean
    public JdbcMutableAclService aclService() {
        return new JdbcMutableAclService(dataSource, lookupStrategy(), aclCache());
    }

    @Bean
    public DefaultMethodSecurityExpressionHandler defaultMethodSecurityExpressionHandler() {
        return new DefaultMethodSecurityExpressionHandler();
    }

    @Override
    public MethodSecurityExpressionHandler createExpressionHandler() {
        DefaultMethodSecurityExpressionHandler expressionHandler = defaultMethodSecurityExpressionHandler();
        expressionHandler.setPermissionEvaluator(new AclPermissionEvaluator(aclService()));
        expressionHandler.setPermissionCacheOptimizer(new AclPermissionCacheOptimizer(aclService()));
        return expressionHandler;
    }
}
@Configuration
@EnableWebSecurity
public class CustomSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Bean
    public AuthenticationEntryPoint entryPoint() {
        return new LoginUrlAuthenticationEntryPoint("/authenticate");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
                .csrf()
                .disable()
                .authorizeRequests()
                .antMatchers("/authenticate/**").permitAll()
                .anyRequest().fullyAuthenticated()
                .and().requestCache().requestCache(new NullRequestCache())
                .and().addFilterBefore(authenticationFilter(), CustomUsernamePasswordAuthenticationFilter.class);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
    }

    @Bean
    public CustomUsernamePasswordAuthenticationFilter authenticationFilter()
            throws Exception {
        CustomUsernamePasswordAuthenticationFilter authenticationFilter = new CustomUsernamePasswordAuthenticationFilter();
        authenticationFilter.setUsernameParameter("username");
        authenticationFilter.setPasswordParameter("password");
        authenticationFilter.setFilterProcessesUrl("/authenticate");
        authenticationFilter.setAuthenticationSuccessHandler(new CustomAuthenticationSuccessHandler());
        authenticationFilter.setAuthenticationFailureHandler(new CustomAuthenticationFailureHandler());
        authenticationFilter.setAuthenticationManager(authenticationManagerBean());
        return authenticationFilter;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
INSERT INTO acl_class VALUES (1, com.company.project.domain.users.User)
INSERT INTO acl_sid VALUES (1, 1, "demo")
参考资料:

安全配置如下:

@Configuration
@ComponentScan(basePackages = "com.company")
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class ACLConfigration extends GlobalMethodSecurityConfiguration {

    @Autowired
    DataSource dataSource;

    @Bean
    public EhCacheBasedAclCache aclCache() {
        return new EhCacheBasedAclCache(aclEhCacheFactoryBean().getObject(), permissionGrantingStrategy(), aclAuthorizationStrategy());
    }

    @Bean
    public EhCacheFactoryBean aclEhCacheFactoryBean() {
        EhCacheFactoryBean ehCacheFactoryBean = new EhCacheFactoryBean();
        ehCacheFactoryBean.setCacheManager(aclCacheManager().getObject());
        ehCacheFactoryBean.setCacheName("aclCache");
        return ehCacheFactoryBean;
    }

    @Bean
    public EhCacheManagerFactoryBean aclCacheManager() {
        return new EhCacheManagerFactoryBean();
    }

    @Bean
    public DefaultPermissionGrantingStrategy permissionGrantingStrategy() {
        ConsoleAuditLogger consoleAuditLogger = new ConsoleAuditLogger();
        return new DefaultPermissionGrantingStrategy(consoleAuditLogger);
    }

    @Bean
    public AclAuthorizationStrategy aclAuthorizationStrategy() {
        return new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_ACL_ADMIN"));
    }

    @Bean
    public LookupStrategy lookupStrategy() {
        return new BasicLookupStrategy(dataSource, aclCache(), aclAuthorizationStrategy(), new ConsoleAuditLogger());
    }

    @Bean
    public JdbcMutableAclService aclService() {
        return new JdbcMutableAclService(dataSource, lookupStrategy(), aclCache());
    }

    @Bean
    public DefaultMethodSecurityExpressionHandler defaultMethodSecurityExpressionHandler() {
        return new DefaultMethodSecurityExpressionHandler();
    }

    @Override
    public MethodSecurityExpressionHandler createExpressionHandler() {
        DefaultMethodSecurityExpressionHandler expressionHandler = defaultMethodSecurityExpressionHandler();
        expressionHandler.setPermissionEvaluator(new AclPermissionEvaluator(aclService()));
        expressionHandler.setPermissionCacheOptimizer(new AclPermissionCacheOptimizer(aclService()));
        return expressionHandler;
    }
}
@Configuration
@EnableWebSecurity
public class CustomSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Bean
    public AuthenticationEntryPoint entryPoint() {
        return new LoginUrlAuthenticationEntryPoint("/authenticate");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
                .csrf()
                .disable()
                .authorizeRequests()
                .antMatchers("/authenticate/**").permitAll()
                .anyRequest().fullyAuthenticated()
                .and().requestCache().requestCache(new NullRequestCache())
                .and().addFilterBefore(authenticationFilter(), CustomUsernamePasswordAuthenticationFilter.class);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
    }

    @Bean
    public CustomUsernamePasswordAuthenticationFilter authenticationFilter()
            throws Exception {
        CustomUsernamePasswordAuthenticationFilter authenticationFilter = new CustomUsernamePasswordAuthenticationFilter();
        authenticationFilter.setUsernameParameter("username");
        authenticationFilter.setPasswordParameter("password");
        authenticationFilter.setFilterProcessesUrl("/authenticate");
        authenticationFilter.setAuthenticationSuccessHandler(new CustomAuthenticationSuccessHandler());
        authenticationFilter.setAuthenticationFailureHandler(new CustomAuthenticationFailureHandler());
        authenticationFilter.setAuthenticationManager(authenticationManagerBean());
        return authenticationFilter;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
INSERT INTO acl_class VALUES (1, com.company.project.domain.users.User)
INSERT INTO acl_sid VALUES (1, 1, "demo")
My
CustomAuthenticationProvider
class:

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private UsersService usersService;

    @Override
    public Authentication authenticate(Authentication authentication)
            throws AuthenticationException {

        String username = authentication.getName();
        String password = authentication.getCredentials().toString();

        User user = usersService.findOne(username);

        if(user != null && usersService.comparePassword(user, password)){

            return new UsernamePasswordAuthenticationToken(
                    user.getUsername(),
                    user.getPassword(),
                    AuthorityUtils.commaSeparatedStringToAuthorityList(
                            user.getUserRoles().stream().collect(Collectors.joining(","))));
        } else {
            return null;
        }
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
}
除上述内容外,我还有
CustomAuthenticationFailureHandler
CustomAuthenticationSuccessHandler
CustomNoRedirectStrategy
customusernamespasswordauthenticationform
,由于这个问题的长度,我跳过了这些内容

我使用的是可以找到的MySQL模式

我正在向acl相关表中添加条目,如下所示:

@Configuration
@ComponentScan(basePackages = "com.company")
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class ACLConfigration extends GlobalMethodSecurityConfiguration {

    @Autowired
    DataSource dataSource;

    @Bean
    public EhCacheBasedAclCache aclCache() {
        return new EhCacheBasedAclCache(aclEhCacheFactoryBean().getObject(), permissionGrantingStrategy(), aclAuthorizationStrategy());
    }

    @Bean
    public EhCacheFactoryBean aclEhCacheFactoryBean() {
        EhCacheFactoryBean ehCacheFactoryBean = new EhCacheFactoryBean();
        ehCacheFactoryBean.setCacheManager(aclCacheManager().getObject());
        ehCacheFactoryBean.setCacheName("aclCache");
        return ehCacheFactoryBean;
    }

    @Bean
    public EhCacheManagerFactoryBean aclCacheManager() {
        return new EhCacheManagerFactoryBean();
    }

    @Bean
    public DefaultPermissionGrantingStrategy permissionGrantingStrategy() {
        ConsoleAuditLogger consoleAuditLogger = new ConsoleAuditLogger();
        return new DefaultPermissionGrantingStrategy(consoleAuditLogger);
    }

    @Bean
    public AclAuthorizationStrategy aclAuthorizationStrategy() {
        return new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_ACL_ADMIN"));
    }

    @Bean
    public LookupStrategy lookupStrategy() {
        return new BasicLookupStrategy(dataSource, aclCache(), aclAuthorizationStrategy(), new ConsoleAuditLogger());
    }

    @Bean
    public JdbcMutableAclService aclService() {
        return new JdbcMutableAclService(dataSource, lookupStrategy(), aclCache());
    }

    @Bean
    public DefaultMethodSecurityExpressionHandler defaultMethodSecurityExpressionHandler() {
        return new DefaultMethodSecurityExpressionHandler();
    }

    @Override
    public MethodSecurityExpressionHandler createExpressionHandler() {
        DefaultMethodSecurityExpressionHandler expressionHandler = defaultMethodSecurityExpressionHandler();
        expressionHandler.setPermissionEvaluator(new AclPermissionEvaluator(aclService()));
        expressionHandler.setPermissionCacheOptimizer(new AclPermissionCacheOptimizer(aclService()));
        return expressionHandler;
    }
}
@Configuration
@EnableWebSecurity
public class CustomSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Bean
    public AuthenticationEntryPoint entryPoint() {
        return new LoginUrlAuthenticationEntryPoint("/authenticate");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
                .csrf()
                .disable()
                .authorizeRequests()
                .antMatchers("/authenticate/**").permitAll()
                .anyRequest().fullyAuthenticated()
                .and().requestCache().requestCache(new NullRequestCache())
                .and().addFilterBefore(authenticationFilter(), CustomUsernamePasswordAuthenticationFilter.class);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
    }

    @Bean
    public CustomUsernamePasswordAuthenticationFilter authenticationFilter()
            throws Exception {
        CustomUsernamePasswordAuthenticationFilter authenticationFilter = new CustomUsernamePasswordAuthenticationFilter();
        authenticationFilter.setUsernameParameter("username");
        authenticationFilter.setPasswordParameter("password");
        authenticationFilter.setFilterProcessesUrl("/authenticate");
        authenticationFilter.setAuthenticationSuccessHandler(new CustomAuthenticationSuccessHandler());
        authenticationFilter.setAuthenticationFailureHandler(new CustomAuthenticationFailureHandler());
        authenticationFilter.setAuthenticationManager(authenticationManagerBean());
        return authenticationFilter;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
INSERT INTO acl_class VALUES (1, com.company.project.domain.users.User)
INSERT INTO acl_sid VALUES (1, 1, "demo")
(我有一个用户名为
demo
的用户)

但我得到的只是:

Denying user demo permission 'READ' on object com.company.project.domain.users.User@4a49e9b4
在我的

我在这里怀疑几个问题:

  • hasPermission
    表达式:我已将其替换为'READ'和'1',但没有达到任何程度
  • 我的数据库条目不正确
  • 我没有实现自定义权限计算器。这是必需的,或者是
    expressionHandler.setPermissionEvaluator(新的AclPermissionEvaluator(aclService())够了吗
  • 更新

    使用
    @PostFilter
    的示例方法:

    @RequestMapping(method = RequestMethod.GET)
        @PostFilter("hasPermission(filterObject, 'READ')")
        List<User> find(@Min(0) @RequestParam(value = "limit", required = false, defaultValue = "10") Integer limit,
                        @Min(0) @RequestParam(value = "page", required = false, defaultValue = "0") Integer page,
                        @RequestParam(value = "email", required = false) String email,
                        @RequestParam(value = "firstName", required = false) String firstName,
                        @RequestParam(value = "lastName", required = false) String lastName,
                        @RequestParam(value = "userRole", required = false) String userRole) {
    
            return usersService.find(
                    limit,
                    page,
                    email,
                    firstName,
                    lastName,
                    userRole);
        }
    
    @RequestMapping(method=RequestMethod.GET)
    @PostFilter(“hasPermission(filterObject,'READ')”)
    列表查找(@Min(0)@RequestParam(value=“limit”,required=false,defaultValue=“10”)整数限制,
    @最小值(0)@RequestParam(value=“page”,required=false,defaultValue=“0”)整数页,
    @RequestParam(value=“email”,required=false)字符串电子邮件,
    @RequestParam(value=“firstName”,required=false)字符串firstName,
    @RequestParam(value=“lastName”,required=false)字符串lastName,
    @RequestParam(value=“userRole”,required=false)字符串(userRole){
    返回usersService.find(
    极限,
    页
    电子邮件,
    名字,
    姓,
    用户角色);
    }
    
    更新#2:

    现在的问题反映了有关身份验证/授权/ACL的所有设置

    更新#3:

    我现在非常接近解决这个问题,唯一剩下的就是解决这个问题:


    如果有人能帮我解决这个问题,我终于可以写一篇我解决这个问题的经历。

    我将我的应用程序升级为使用Spring Security 4.2.1.RELEASE,然后我开始在所有
    @PreAuthorize
    注释的方法中遇到意外的访问被拒绝,在升级之前,它工作得很好。 我调试了spring安全代码,发现问题是所有要检查的角色都以默认字符串“ROLE_uz”作为前缀,而不管我是否已将默认前缀设置为空,如下面的代码所示

    auth.ldapAuthentication()
            .groupSearchBase(ldapProperties.getProperty("groupSearchBase"))
            .groupRoleAttribute(ldapProperties.getProperty("groupRoleAttribute"))
            .groupSearchFilter(ldapProperties.getProperty("groupSearchFilter"))
    
            //this call used to be plenty to override the default prefix
            .rolePrefix("")
    
            .userSearchBase(ldapProperties.getProperty("userSearchBase"))
            .userSearchFilter(ldapProperties.getProperty("userSearchFilter"))
            .contextSource(this.ldapContextSource);
    
    所有我的控制器方法都用
    @PreAuthorize(“hasRole('my_ldap_group_name'))”
    注释,但是,框架没有考虑我的空角色前缀设置,因此它使用角色\u我的ldap_group_name来检查实际的角色

    在深入研究框架的代码之后,我意识到类
    org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler
    仍然将默认角色前缀设置为
    “role\ux”
    。我跟踪了它的值的来源,发现它首先检查类
    org.springframework.security.config.core.GrantedAuthorityDefaults
    的声明bean,以便在bean的第一次初始化期间查找默认前缀
    org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer
    ,但是,由于此初始值设定项bean找不到它声明的值,它最终使用了前面提到的默认前缀

    我相信这不是一个预期的行为:Spring安全性应该考虑与ldapAuthentication相同的rolePrefix,但是,为了解决这个问题,有必要将bean
    org.springframework.Security.config.core.GrantedAuthorityDefaults
    添加到我的应用程序上下文中(我使用的是基于注释的配置),详情如下:

    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class CesSecurityConfiguration extends WebSecurityConfigurerAdapter {
    
        private static final String ROLE_PREFIX = "";
        //... ommited code ...
        @Bean
        public GrantedAuthorityDefaults grantedAuthorityDefaults() {
            return new GrantedAuthorityDefaults(ROLE_PREFIX);
        }
    
    }
    

    也许你也遇到了同样的问题-我可以看到你使用的是DefaultMethodSecurityExpressionHandler,它还使用了bean授权的AuthorityDefaults,因此如果你使用的是与我相同的Spring安全版本-4.2.1.RELEASE,你可能会遇到同样的问题。

    你的数据库数据和配置看起来都不错。我一直使用
    @PostFilter(“hasPermission(filterObject,'READ')”

    我会检查以确保扩展UserDetails的用户类通过数据库中的getUsername()返回相同的用户名。同时检查以确保您的安全性和应用程序处于相同的上下文中

    该方法将对象作为其第一个参数

    boolean hasPermission(Authentication authentication,
                          Object targetDomainObject,
                          Object permission)
    
    身份验证对象是一个实现类,通常为。因此getPrincipal()方法需要返回一个对象,该对象具有一个getUserName()方法,该方法返回与数据库中相同的内容

    看看


    这是等待已久的答案:

    报告清楚地描述了:

    要使用hasPermission()表达式,必须显式配置 应用程序上下文中的PermissionEvaluator。这看起来 大概是这样的:

    所以基本上我是在我的
    AclConfiguration
    中进行的,它扩展了
    GlobalMethodSecurityConfiguration

        @Override
        protected MethodSecurityExpressionHandler createExpressionHandler() {
            DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
            expressionHandler.setPermissionEvaluator(new AclPermissionEvaluator(aclService()));
            expressionHandler.setPermissionCacheOptimizer(new AclPermissionCacheOptimizer(aclService()));
            return expressionHandler;
        }
    
    这不是由Spring处理的

    我必须将
    AclConfig
    GlobalMethodSecurityConfiguration
    分开。如果在后者中定义了
    @Bean
    s,则不会处理上述方法,这可能会导致