GithubHelp home page GithubHelp logo

ptzagk / strategy-spring-security-acl Goto Github PK

View Code? Open in Web Editor NEW

This project forked from lordlothar99/strategy-spring-security-acl

0.0 0.0 0.0 472 KB

Extensible strategy-based Spring Security ACL implementation ; available modules are : PermissionEvaluator, JPA Specification and ElasticSearch Filter

License: Apache License 2.0

Java 100.00%

strategy-spring-security-acl's Introduction

strategy-spring-security-acl Build Status Coverage Status GitHub tag

Extensible strategy-based Spring Security ACL implementation ; available modules are : PermissionEvaluator, JPA Specification and ElasticSearch Filter

How to install : have a look here : Installation

Why ??

### Default Spring Security ACL implementation is database-oriented

Spring Security ACL default implementation uses a persistent model in order to evaluate every permission for any object and SID. Aside performance issues due to a huge ternary table in this model (1 row is 3-tuple { sid ; object weak reference ; permission }), developpers would rather use a more programmatic and object-oriented implementation, without any duplication.

Access Control List is not only a PermissionEvaluator concern

Dealing with Access Control List is not a PermissionEvaluator-only concern. Let's take a CRUD-like standard application :

  • Create, Update and Delete methods should be annotated with @PreAuthorize("hasPermission(<object>, <permission>)"), and so would reject unauthorized executions, that's great !
  • But Read methods would use @PostAuthorize("hasPermission(<object>, <permission>)") instead, and therefore try to filter objects after they've been retrieved from underlying layers (often database) ; this leads to two frequent issues:
  • performance : some useless objects are retrieved but evicted
  • pagination : let's say user ask for a 10 items page ; repository finds those, but 4 of them are evicted... either developper implemented some retry-til-page-is-complete behavior (ugly pattern, and downgraded performance expected...), either client will get only 6 objects, and therefore ask himself where the 4 others went !! too bad...

For read-like methods in JPA and ElasticSearch repositories, Strategy-spring-security-acl provides features able to inject ACL restriction criterias directly inside the repositories.

Auto-configured

Strategy-security-acl is an extension of Spring Security which will auto-configure thanks to Spring Boot awesome magic

Extensibility !!

Current bundled features are:

  • Grant : implementation of PermissionEvaluator which delegates to adequate GrantEvaluator beans
  • JPA : injects JpaSpecification in your repositories so they would retrieve only authorized objects from database ; thanks to Spring Data JPA
  • ElasticSearch : injects FilterBuilder in your repositories so they would retrieve only authorized objects from ElasticSearch ; thanks to Spring Data ElasticSearch You need more than existing features ? Create your own !! and share it ;).

Strategy oriented

  1. ACL strategies are Spring beans
  2. You can create reusable strategies, and apply them to several domain objects, or associate 1 specific strategy for each domain object
  3. Strategies are composite objects wrapping ACL filter implementations dedicated to each supported technology, which are called "feature" :

## Installation

Add Github as a maven repository (yes, you can) :

<repositories>
	<repository>
		<id>strategy-spring-security-acl-github-repo</id>
		<url>https://raw.github.com/lordlothar99/mvn-repo/master/</url>
		<snapshots>
			<enabled>false</enabled>
		</snapshots>
	</repository>
</repositories>

### Spring Boot

Configured beans are automatically loaded by Spring Boot's magic, as soon jars are in the path. Add required dependencies to your pom (latest version is highest tag created on Github : GitHub tag) :

<dependency>
	<groupId>com.github.lothar.security.acl</groupId>
	<artifactId>strategy-spring-security-acl-elasticsearch</artifactId>
	<version>LATEST</version>
</dependency>

<dependency>
	<groupId>com.github.lothar.security.acl</groupId>
	<artifactId>strategy-spring-security-acl-grant</artifactId>
	<version>LATEST</version>
</dependency>

<dependency>
	<groupId>com.github.lothar.security.acl</groupId>
	<artifactId>strategy-spring-security-acl-jpa</artifactId>
	<version>LATEST</version>
</dependency>

Integration

Then you need very few Spring config:

  • For Jpa feature :
	import com.github.lothar.security.acl.jpa.repository.AclJpaRepositoryFactoryBean;
...
	@EnableJpaRepositories(
		value = "<your jpa repositories package here>",
		repositoryFactoryBeanClass = AclJpaRepositoryFactoryBean.class
	)
  • For ElasticSearch feature :
	import com.github.lothar.security.acl.elasticsearch.repository.AclElasticsearchRepositoryFactoryBean;
...
	@EnableElasticsearchRepositories(
		value = "<your elastic search repositories package here>",
		repositoryFactoryBeanClass = AclElasticsearchRepositoryFactoryBean.class
	)
  • For GrantEvaluator feature (if you want to enable Pre/Post annotations) :
	@EnableGlobalMethodSecurity(prePostEnabled = true)

Now, let's say you have a Customer domain entity in your project, and you need to restrict readable customers, so that only those whose last name is "Smith" can be retrieved.

  1. Define your strategy : let's create an CustomerAclStrategy, which will contain our different ACL features implementations (1 implementation by feature). SimpleAclStrategy implementation is recommended as a start. In your favorite Configuration bean, let's define :
  @Bean
  public SimpleAclStrategy customerStrategy() {
    return new SimpleAclStrategy();
  }
  1. If you are using GrantEvaluator feature, create a CustomerGrantEvaluator bean, and install it inside the CustomerStrategy. Let's add a new bean into Configuration :
  @Bean
  public GrantEvaluator smithFamilyGrantEvaluator(CustomerRepository customerRepository,
      GrantEvaluatorFeature grantEvaluatorFeature) {
    GrantEvaluator smithFamilyGrantEvaluator = new CustomerGrantEvaluator(customerRepository);
    customerStrategy.install(grantEvaluatorFeature, smithFamilyGrantEvaluator);
    return smithFamilyGrantEvaluator;
  }

And create a dedicated CustomerGrantEvaluator class, it's close to Spring's PermissionEvaluator API :

import static com.github.lothar.security.acl.jpa.spec.AclJpaSpecifications.idEqualTo;
import org.springframework.security.core.Authentication;
import com.github.lothar.security.acl.sample.domain.Customer;
import com.github.lothar.security.acl.sample.jpa.CustomerRepository;

public class CustomerGrantEvaluator extends AbstractGrantEvaluator<Customer, String> {

  private CustomerRepository repository;

  public CustomerGrantEvaluator(CustomerRepository repository) {
    super();
    this.repository = repository;
  }

  @Override
  public boolean isGranted(Permission permission, Authentication authentication,
      Customer domainObject) {
    return "Smith".equals(domainObject.getLastName());
  }

  @Override
  public boolean isGranted(Permission permission, Authentication authentication, String targetId,
      Class<? extends Customer> targetType) {
    // thanks to JpaSpecFeature, repository will count only authorized customers !
    return repository.count(idEqualTo(targetId)) == 1;
  }
}
  1. Add Pre/Post annotations on adequate methods :
  @PreAuthorize("hasPermission(#customer, 'SAVE')")
...
  @PreAuthorize("hasPermission(#customerId, 'com.github.lothar.security.acl.sample.domain.Customer', 'READ')")
  1. If you are using Jpa feature, create a Specification bean, and install it inside the CustomerStrategy. Let's add this new bean into Configuration :
  @Bean
  public Specification<Customer> smithFamilySpec(JpaSpecFeature<Customer> jpaSpecFeature) {
    Specification<Customer> smithFamilySpec = new Specification<Customer>() {
      @Override
      public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query,
          CriteriaBuilder cb) {
        return cb.equal(root.get("lastName"), "Smith");
      }
    };
    customerStrategy.install(jpaSpecFeature, smithFamilySpec);
    return smithFamilySpec;
  }
  1. If you are using ElasticSearch feature, create a FilterBuilder bean, and install it inside the CustomerStrategy. Let's add this new bean into Configuration :
  @Bean
  public TermFilterBuilder smithFamilyFilter(ElasticSearchFeature elasticSearchFeature) {
    TermFilterBuilder smithFamilyFilter = termFilter("lastName", "Smith");
    customerStrategy.install(elasticSearchFeature, smithFamilyFilter);
    return smithFamilyFilter;
  }

Exclude a Spring Data JPA query-method to be filtered with ACL

You just have to put @NoAcl annotation on this method in order to avoid the ACL JPA Specification to be injected.

Override strategies

It may be useful (for tests purpose for example) to disable all domain objects strategies, and use only one (which may be allowAllStrategy, so no restriction would be applied). Just add following property in your project's yml/properties file:

strategy-security-acl:
    override-strategy: allowAllStrategy

### Struggling with integration ?

Have a look at our samples !!

Using JDK 7 ?

Projects using JDK 7 can use artifacts version with suffix "jdk7"

strategy-spring-security-acl's People

Contributors

lordlothar99 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.