Matt Immer
Matt Immer

Reputation: 509

Is there a good design pattern for checking permissions when running a method?

I'm looking for a design pattern or a approach to tidy up my code. This is in the context of security and checking permissions for a given subject. Here is a simplified example:

public Pizza bakePizza() throws UnauthorizedException{
if (subject.isPermitted("BAKE_PIZZA")){
        return new Pizza();
    } else {
        throw new UnauthorizedException();
    }
}

Is there a way to make this a bit more clean because this can get quite messy when I have a lot of different kinds of methods like this.

Upvotes: 4

Views: 1785

Answers (2)

zapl
zapl

Reputation: 63955

One approach is to move the check logic into a method that throws and thereby ends the program flow of the calling method early.

public Pizza bakePizza() throws UnauthorizedException{
    ensurePermission("BAKE_PIZZA");
    return new Pizza();
}

private void ensurePermission(String permission) throws UnauthorizedException {
    if (!subject.isPermitted(permission))
        throw new UnauthorizedException();
}

Upvotes: 0

micha
micha

Reputation: 49612

I think splitting security constraints and bussines logic by using something like the decorator pattern would be a good start.

How about something like this:

// an interface defines the operations
public interface PizzaService {
  Pizza bakePizza();
}

// standard implementation that contains the business logic
public class PizzaServiceImpl implements PizzaService {
  @Override
  public Pizza bakePizza() {
    // implementation ..
  }
}

// implementation with security constraints that delegates to the real implementation
public class SecurePizzaService implements PizzaService {
  private PizzaService service;
  public SecurePizzaService(PizzaService service) {
    this.service = service;
  }

  @Override
  public Pizza bakePizza() {
    if (!subject.isPermitted("BAKE_PIZZA")){
      throw new UnauthorizedException();
    }
    service.bakePizza()
  }
}

// usage
PizzaService pizzaService = new SecurePizzaService(new PizzaServiceImpl());
...
Pizza pizza = pizzaService.bakePizza();

This way you could change security constraints without touching business logic and vice versa.

If you have a lot of situations like this you should have a look at AOP frameworks like AspectJ

Upvotes: 4

Related Questions