Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8/Spring constants in PreAuthorize annotation

In my Spring Boot project I have defined a following RestController method:

@PreAuthorize("hasAuthority('" + Permission.APPEND_DECISION + "')")
@RequestMapping(value = "/{decisionId}/decisions", method = RequestMethod.PUT)
public DecisionResponse appendDecisionToParent(@PathVariable @NotNull @DecimalMin("0") Long decisionId, @Valid @RequestBody AppendDecisionRequest decisionRequest) {
    ....
    return new DecisionResponse(decision);
}

Right now in order to provide allowed authority name I use a following code construction:

@PreAuthorize("hasAuthority('" + Permission.APPEND_DECISION + "')")

where Permission.APPEND_DECISION is a constant:

public static final String APPEND_DECISION = "APPEND_DECISION";

Is there any more elegant way in Java/Spring in order to define such kind of code ?

like image 674
alexanoid Avatar asked Jan 27 '17 10:01

alexanoid


People also ask

How does PreAuthorize work spring?

Spring Security provides method level security using @PreAuthorize and @PostAuthorize annotations. This is expression-based access control. The @PreAuthorize can check for authorization before entering into method. The @PreAuthorize authorizes on the basis of role or the argument which is passed to the method.

What is @PreAuthorize?

The @PreAuthorize annotation checks the given expression before entering the method, whereas the @PostAuthorize annotation verifies it after the execution of the method and could alter the result.


2 Answers

Here is a simple approach to defining authorities in a single place that doesn't require any in-depth Spring Security config.

public class Authority {
    public class Plan{
        public static final String MANAGE = "hasAuthority('PLAN_MANAGE')";
        public static final String APPROVE = "hasAuthority('PLAN_APPROVE')";
        public static final String VIEW = "hasAuthority('PLAN_VIEW')";
    }
}

Securing services...

public interface PlanApprovalService {

    @PreAuthorize(Authority.Plan.APPROVE)
        ApprovalInfo approvePlan(Long planId);

    }
}
like image 164
BreakerOfStones Avatar answered Sep 19 '22 10:09

BreakerOfStones


Thanks to oli37 I have implemented this logic in a following way:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {

    private DefaultMethodSecurityExpressionHandler defaultMethodExpressionHandler = new DefaultMethodSecurityExpressionHandler();

    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        return defaultMethodExpressionHandler;
    }

    public class DefaultMethodSecurityExpressionHandler extends org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler {

        @Override
        public StandardEvaluationContext createEvaluationContextInternal(final Authentication auth, final MethodInvocation mi) {
            StandardEvaluationContext standardEvaluationContext = super.createEvaluationContextInternal(auth, mi);
            ((StandardTypeLocator) standardEvaluationContext.getTypeLocator()).registerImport(Permission.class.getPackage().getName());
            return standardEvaluationContext;
        }
    }

}


    @PreAuthorize("hasAuthority(T(Permission).APPEND_DECISION)")
    @RequestMapping(value = "/{decisionId}/decisions", method = RequestMethod.PUT)
    public DecisionResponse appendDecisionToParent(@PathVariable @NotNull @DecimalMin("0") Long decisionId, @Valid @RequestBody AppendDecisionRequest decisionRequest) {
    ...
        return new DecisionResponse(decision);
    }
like image 33
alexanoid Avatar answered Sep 19 '22 10:09

alexanoid