как контролировать аутентификацию пользователя с помощью Spring MVC - PullRequest
1 голос
/ 28 октября 2011

Я использую Spring mvc3 для построения системы user-manager.

Эта система включает следующие модели:

Department
User

А департаменты имеют иерархическую структуру, например:

Dep1
  SubDep1
  SubDep2
    Sub_sub_dep1
    xxxx

Можно добавлять / обновлять / удалять отделы / пользователей, если он авторизован, но он может выполнять эти операции только в своем отделе и подотделах.

Например, есть три отдела (с их пользователями):

Dep01(user1:{id:1}}
  Dep0101(user2:{id:2}
  Dep0102(user3:{id:3}
    Dep010201(user4:{id:4}

Таким образом, user1 может сделать / добавить / обновить / удалить всех пользователей (user1, user2, user3, user4)

Пока пользователь user3 может выполнять эту операцию только для пользователя (user3, user4).

Я могу контролировать, что user3 не может видеть user1 и user2 на странице department/list.

Но как насчет того, если он введет URL так:

department/update/1

Этого следует избегать, поскольку user1 (идентификатор которого равен 1) не принадлежит Dep0102 или Dep010201.

Как это контролировать?

1 Ответ

3 голосов
/ 28 октября 2011

Один из вариантов - создать собственный 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"/>

Удачи!

...