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 ?
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.
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.
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);
}
}
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With