Java – ACL security in spring boot

I encountered a problem setting ACL through Java configuration in spring boot application I created a small project to reproduce the problem

I've tried several different methods The first problem I encountered was ehcache. After I repaired it (I assumed I did it), I could no longer log in. It seemed that all the data disappeared

There are four classes with different configurations:

ACLConfig1.class
ACLConfig2.class
ACLConfig3.class
ACLConfig4.class

All @ preauthorize and @ postauthorize annotations work as expected, except for haspermission

The controller has four endpoints: one for user, one for admin, one for public, and the last one gives me a headache @ postauthorize ("haspermission (returnobject, 'administration')")

I'm pretty sure the insertion in DB is correct This class is one of the four and the last one I tried:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true)
public class ACLConfig4 {

@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_ADMINISTRATOR"));
}

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

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

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

@Bean
public MethodSecurityExpressionHandler createExpressionHandler() {
    DefaultMethodSecurityExpressionHandler expressionHandler = defaultMethodSecurityExpressionHandler();
    expressionHandler.setPermissionEvaluator(new AclPermissionEvaluator(aclService()));
    expressionHandler.setPermissionCacheOptimizer(new AclPermissionCacheOptimizer(aclService()));
    return expressionHandler;
}


}

What did I miss here? If I use aclconfig3 Class or why I don't have data aclconfig4 class. Is there an example of how to configure spring boot programmatically?

Solution

It's a bit tricky not to find the reason why you don't have data As long as the methodsecurityexpressionhandler bean is defined in the configuration, there is no data in the database table This is because of your data SQL file not executed

Explaining why the data is not executed Before SQL, I'll first point out that you didn't use the file as expected

After hibernate is initialized, spring Sboot executes data SQL, usually contains only DML statements Your data SQL contains DDL (schema) statements and DML (data) statements This is not ideal because some DDL statements are related to hibernate hbm2ddl. Auto behavior conflicts (note that when using an embedded datasource, spring boot uses' create drop ') You should put your DDL statements in schema. XML In SQL, put the DML statement in data In SQL Hibernate should be disabled when you manually define all tables hbm2ddl. Auto (by adding spring.jpa.hibernate.ddl-auto = none to applciation.properties)

Having said that, let's see why we didn't execute data sql.

data. SQL execution is triggered by an applicationevent triggered by beanpostprocessor This beanpostprocessor (datasourceinitialized publisher) was created as part of Hibernate / JPA auto configuration for spring boot (see org.springframework.boot.autoconfigure.orm.jpa.hibernatejpaautoconfiguration, org.springframework.boot.autoconfigure.orm.jpa.datasourceinitializedpublisher and org. Springframework. Boot. Autoconfigure. JDBC. Datasourceinitializer)

Usually, datasourceinitializedpublisher is created before creating (embedding) datasource, and everything works as expected, but by defining a custom methodsecurityexpressionhandler, the normal bean creation order will change After configuring @ enablegrobalmethodsecurity, you will automatically import globalmethodsecurityconfiguration

Spring - Security - related beans are created early Because your methodsecurityexpressionhandler needs the data source of ACL resources, and spring security related beans need your custom methodsecurityexpressionhandler, the datasource is created earlier than usual; In fact, it was created early in spring boot's datasourceinitialized publisher Datasourceinitializedpublisher will be created later, but because it does not notice the creation of datasource bean, it will not trigger data SQL execution

Long story short: security configuration changes the normal bean creation order, resulting in data SQL was not loaded

I think fixing the bean creation order can solve this problem, but I don't know how (no further experiment) I propose the following solution: manually define your datasource and be responsible for data initialization

@Configuration
public class DataSourceConfig {
    @Bean
    public EmbeddedDatabase dataSource() {
        return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2)
                 //as your data.sql file contains both DDL & DML you might want to rename it (e.g. init.sql)
                .addScript("classpath:/data.sql")
                .build();
    }
}

Due to data The SQL file contains all the DDLS required by the application, so hibernate. SQL can be disabled hbm2ddl. auto. Add spring jpa. hibernate. DDL auto = none added to application properties.

When defining your own datasource, the datasourceautoconfiguration of spring boot usually exits, but you can also exclude it if you want to be sure (optional)

@SpringBootConfiguration
@EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class)
@ComponentScan
@EnableCaching
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }

}

This should solve your "no data" problem But in order for everything to work as expected, you need to make two more modifications

First, you should define only one methodsecurityexpressionhandler bean Currently, you are defining 2 methodsecurityexpressionhandler beans Spring security doesn't know which one to use, but (silently) uses its own internal methodsecurityexpressionhandler See org springframework. security. config. annotation. method. configuration. GlobalMethodSecurityConfiguration #setMethodSecurityExpressionHandler.

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true)
public class MyACLConfig {

    //...
    @Bean
    public MethodSecurityExpressionHandler createExpressionHandler() {
        DefaultMethodSecurityExpressionHandler securityExpressionHandler = new DefaultMethodSecurityExpressionHandler();
        securityExpressionHandler.setPermissionEvaluator(new AclPermissionEvaluator(aclService()));
        securityExpressionHandler.setPermissionCacheOptimizer(new AclPermissionCacheOptimizer(aclService()));
        return securityExpressionHandler;
    }

}

The last thing you need to do is set the getid () method in the car to public

@Entity
public class Car {
    //...    
    public long getId() {
        return id;
    }
    //...
}

When trying to determine the identity of an object during ACL permission evaluation, the standard objectidentityretrievalstrategy looks for the public method 'getid()'

(please note that my answer is based on aclconfig4.)

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>