весенняя безопасность | Безопасность на уровне метода с помощью @Secured/@PreAuthorize

Я пробовал безопасность «Уровня метода» в этом приложении, над которым я работал. Идея состоит в том, чтобы защитить метод, который вызывается с уровня представления, используя DWR. Теперь я попытался добавить следующие аннотации к своему методу:

@PreAuthorize("isAuthenticated() and hasRole('ROLE_CUSTOMER')")

И соответствующая запись в моем контексте безопасности:

<global-method-security pre-post-annotations="enabled" />

Аналогичным образом я пробовал аннотацию @Secured:

@Secured({"ROLE_CUSTOMER" })

И соответствующая запись в моем контексте безопасности:

<global-method-security secured-annotations="enabled" />

В идеале я ожидаю, что если пользователь не аутентифицирован, он должен быть перенаправлен на страницу «Войти», а «РОЛИ» не должны проверяться. В этом случае даже для пользователя, не прошедшего проверку подлинности, вызов этого метода приводит к «AccessDeniedException». Мне нужно, чтобы перенаправить пользователя на страницу входа в такой сценарий.

Чтобы продвинуться вперед, я даже попытался обработать исключение, связанное с отказом в доступе, создав собственный обработчик отказа в доступе. К сожалению, обработчик так и не был вызван, но было выдано исключение.

Вот конфигурация:

<access-denied-handler ref="customAccessDeniedHandler"/>

Для этого есть соответствующий bean-компонент обработчика, определенный в том же файле.

Все равно не повезло. Обработчик отказа в доступе никогда не вызывается.

Чтобы обобщить требование, мне нужно защитить метод. Если этот метод вызывается, а пользователь не аутентифицирован, пользователь должен быть перенаправлен на страницу «Войти» (которая на данный момент выдает исключение Accessdenied).

Ценю вашу помощь, люди..

EDIT 1: Вот фрагмент из контекста безопасности:

<http>
    <intercept-url pattern="/*sign-in.do*" requires-channel="$secure.channel}" />
    .....
    ..... 
    .....
    <intercept-url pattern="/j_acegi_security_check.do" requires-channel="${secure.channel}" />

    <intercept-url pattern="/*.do" requires-channel="http"  />
    <intercept-url pattern="/*.do\?*" requires-channel="http" />
    <form-login login-page="/sign-in.do" authentication-failure-url="/sign-in.do?login_failed=1"
        authentication-success-handler-ref="authenticationSuccessHandler" login-processing-url="/j_acegi_security_check.do"/>

    <logout logout-url="/sign-out.do" logout-success-url="/index.do" />

    <session-management session-authentication-strategy-ref="sessionAuthenticationStrategy" />
        <access-denied-handler ref="customAccessDeniedHandler"/>
  </http>
    <beans:bean id="customAccessDeniedHandler" class="com.mypackage.interceptor.AccessDeniedHandlerApp"/>

person va1b4av    schedule 07.05.2013    source источник


Ответы (3)


Я не очень хорошо знаком с DWR, но знаю, что это механизм RPC. Проблема в том, что запрос RPC, отправленный javascript на стороне клиента, не является обычным запросом страницы, инициированным пользователем, который перемещается по браузеру. Ответ на такой запрос RPC не может заставить браузер уйти с текущей страницы, потому что ответ обрабатывается вашим кодом javascript, а не браузером.

Что вы можете сделать, это:

  1. Реализуйте своего рода активную аутентификацию: перенаправьте пользователя на простую страницу входа .jsp, прежде чем разрешить ему доступ к веб-приложению (URL), которое делает запросы DWR (или любого типа RPC).
  2. Если AccessDeniedException, созданный удаленной процедурой, передается на сторону клиента в той или иной форме, вы можете попытаться обработать его из кода javascript, например, открыв диалоговое окно входа и отправив учетные данные пользователя в запросе AJAX. (В этом случае обязательно сохраните возвращенный идентификатор сеанса и отправьте его обратно с каждым последующим запросом.)
person zagyi    schedule 07.05.2013
comment
Спасибо за ответ, zagyi.. Я понял идею. Однако, если бы мы полностью исключили dwr из картины и предположили, что защищенный метод вызывается через контроллер Spring MVC, даже тогда я получаю исключение с отказом в доступе, и пользовательский обработчик не будет вызываться. Любое обходное решение, которое вы можете предложить здесь? - person va1b4av; 07.05.2013
comment
Можете ли вы поделиться всей конфигурацией безопасности? Это было бы необходимо, чтобы помочь вам решить эту проблему. - person zagyi; 07.05.2013
comment
Zagyi, что касается вашего первого предложения, URL-адрес, который делает вызов dwr, уже является защищенной страницей. Однако проблема возникает в случае тайм-аутов сеанса. В этом случае вызов dwr все равно проходит. В качестве обходного пути я создал фильтр dwr ajax, который перехватывает все вызовы dwr и потенциально может проверять, вошел ли пользователь в систему или имеет ли действительный сеанс. Просто не кажется лучшим способом сделать это. - person va1b4av; 09.05.2013

Мне было бы интересно увидеть остальную часть вашего файла security.xml (в частности, элемент <http>), потому что, если каждому пользователю отказано, мне кажется, что у вас есть свойство <intercept-url>, которое переопределяет вызовы вашего класс(ы) контроллера. Если нет, добавленная информация может помочь пролить свет на проблему.

Предполагая, что я далеко ушел, другой вероятной точкой ошибки может быть сам указанный access-denied-page -- если его путь является защищенным путем (то есть <intercept-url>) или если он не указан, вы можете увидеть ошибки, которые вы разговаривать.

Конечно, я тоже не знаком с DWR, поэтому я несколько очевидно предполагаю стандартную структуру Spring MVC...

person cabbagery    schedule 07.05.2013
comment
Привет капуста и zagyi, Спасибо за ваши ответы. Вот обрезанная версия контекста безопасности. Файл был большим, поэтому я удалил некоторые разделы. Дайте мне знать, если вам нужна дополнительная информация. - person va1b4av; 08.05.2013
comment
Просто добавлю, что я был бы счастлив, если бы смог заставить это работать с контроллерами Spring, вызывающими методы безопасного обслуживания. Я могу покончить с DWR прямо сейчас. Очень ценю ваше время. - person va1b4av; 08.05.2013

Хорошо, мне не удалось выяснить, почему я получил исключение AccessDeniedException. Тем не менее, я работал над этим, пока не нашел причину. Вот несколько подходов, которые я использовал:

1) Как упоминал Zagyi, я смог передать исключение AccessDenied Exception на сторону клиента. Я мог бы создать обработчик исключений и перенаправить пользователя на страницу входа.

Однако я выбрал другой подход (который может быть не самым оптимальным, но, похоже, работает на данный момент. Вот что я сделал:

1) Создал DWRAjaxFilter и сопоставил только интересующие меня удаленные объекты. Это будет означать, что фильтр перехватывает только вызовы DWR к этим удаленным методам. Это связано с тем, что я не хочу, чтобы все открытые методы DWR использовались как для входа.

   <create creator="spring" javascript="downloadLinksAjaxService">
       <param name="beanName" value="downloadLinksAjaxService" />
       <include method="methodOne" />
       <include method="methodTwo" />  
       <filter class="com.xyz.abc.interceptor.DwrAjaxFilter"></filter>
   </create>

2) Вот фактическая реализация фильтра:

public class DwrSessionFilter implements AjaxFilter {
    public Object doFilter(final Object obj, final Method method,
            final Object[] params, final AjaxFilterChain chain)
            throws Exception {

        SecurityContext context = SecurityContextHolder.getContext();
        Authentication auth = context.getAuthentication();
        if (!auth.isAuthenticated()
                || auth.getAuthorities().contains(
                        new GrantedAuthorityImpl("ROLE_ANONYMOUS"))) {
            throw new LoginRequiredException("Login Required");
        } else {
            return chain.doFilter(obj, method, params);
        }
    }
}

3) Вот обработчик на стороне клиента:

function errorHandler(message, exception){

                if(exception && exception.javaClassName == "org.directwebremoting.extend.LoginRequiredException") {

                  document.location.reload();
                }
            }

4) Я также добавил и сопоставитель исключений для DWR, чтобы я мог преобразовывать исключения JAVA в исключения JS:

<convert match="java.lang.Exception" converter="exception">
            <param name='include' value='message'/>
        </convert> 

5) Кажется, это работает хорошо на данный момент. Я все еще тестирую это, чтобы увидеть, не сработает ли где-нибудь.

Был бы признателен за любые дополнительные материалы.

person va1b4av    schedule 10.05.2013