Один из вариантов - создать собственный Spring Security PermissionEvaluator
и реализовать свои пользовательские проверки методом hasPermission(Authentication authentication, Object targetDomainObject, Object permission)
.
Подпись метода защиты выглядит примерно так:
@PreAuthorize("hasRole('ROLE_USER') and hasPermission(#_dept, 'deptAndSubs')")
public String methodToProtect(String _dept)throws Exception {
<custom code>;
}
Первый аргумент выражения hasPermission
- это отдел, который пользователь хочет изменить, а второй - это разрешение. Для нас разрешение deptAndSubs указывает, что пользователь может выполнять метод только в том случае, если изменяемый отдел равен назначенному пользователю отделу или любому из подразделений этого отдела (другие разрешения - «deptOnly» и «subsOnly»).
В нашем приложении есть пользовательский объект Spring Security UserDetails
, который включает код отдела пользователя, поэтому мы можем получить зарегистрированный отдел пользователя непосредственно из объекта Authentication, который Spring передает в метод. Вот как в конечном итоге выглядит пользовательский оценщик:
public class CustomPermissionEvaluator implements PermissionEvaluator {
@Override
public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
AppUser appUser = (AppUser)authentication.getPrincipal();
if(permission instanceof String){
if("deptAndSubs".equals(permission)){
return isTargetDeptInUserDeptTree((String)targetDomainObject, appUser.getDeptCode());
}else if(.... other permission checks){}
}
return false;
}
Метод isTargetDeptInUserDeptTree - это пользовательский код для извлечения дерева отделов пользователя и проверки наличия в нем целевого отдела.
Наконец, вам нужно настроить конфигурацию xml:
<global-method-security pre-post-annotations="enabled" >
<expression-handler ref="expressionHandler"/>
</global-method-security>
<beans:bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
<beans:property name="permissionEvaluator" ref="customPermissionEvaluator"/>
</beans:bean>
<beans:bean id="customPermissionEvaluator" class="....CustomPermissionEvaluator"/>
Удачи!