Как обрабатывать HTTP 403 с помощью Spring Security 3.0.x

Я столкнулся с небольшой проблемой с Spring Security 3.0.x(в частности, 3.0.2). Все приложение, над которым я работаю, отлично работает, за исключением случаев, когда кто-то, у кого нет полномочий, пытается войти в систему.

Когда это происходит, пользователи перенаправляются на страницу приветствия, так как его имя пользователя/пароль действительны, и он получает милую белую страницу с этим: "Ошибка 403: доступ запрещен"

Итак, я искал сеть, пытаясь найти, как это поведение может быть обработано. До сих пор я пришел к выводу, пожалуйста, исправьте меня, если я ошибаюсь, что он управляется ExceptionTranslationFilter. Но я не совсем понимаю, как эффективно использовать эту информацию.

Я попытался изменить свой SecurityContext.xml, чтобы добавить тег access-denied-handler к тегу http, но он не работает. Нужно ли добавлять больше, чем этот тег, чтобы заставить его работать? Есть ли другие возможности сделать приложение более удобным?

Изменить. Я хотел бы перенаправить на страницу, например, 403.html.

Искренне,
Благодаря

Ответ 1

Я нашел, как это сделать. Внедряя AccessDeniedHandler интерфейс и соответствующий метод дескриптора, я могу легко контролировать способ обработки ошибки Http 403.

Таким образом, вы можете добавлять различные элементы в сеанс, а затем перехватывать их на jsp.

Затем xml файл выглядит следующим образом:

<sec:http>
    <!-- lots of urls here -->
    <sec:access-denied-handler ref="accessDeniedHandler" />
    <sec:anonymous/>
</sec:http>

<bean id="accessDeniedHandler" class="foo.bar.CustomAccessDeniedHandler">
    <property name="accessDeniedUrl" value="403.html" />
</bean>

Класс java:

package foo.bar;
public class CustomAccessDeniedHandler implements org.springframework.security.web.access.AccessDeniedHandler {
private String accessDeniedUrl;

    public CustomAccessDeniedHandler() {
    }

    public CustomAccessDeniedHandler(String accessDeniedUrl) {
        this.accessDeniedUrl = accessDeniedUrl;
    }

    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        response.sendRedirect(accessDeniedUrl);
        request.getSession().setAttribute("CustomSessionAttribute", "value here");
    }

    public String getAccessDeniedUrl() {
        return accessDeniedUrl;
    }

    public void setAccessDeniedUrl(String accessDeniedUrl) {
        this.accessDeniedUrl = accessDeniedUrl;
    }
}

И пример jsp:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
 <c:if test="${!empty CustomSessionAttribute}">
    <br/>
    ACCESS IS DENIED
    <br/>
 </c:if>
<!-- other stuff down here -->

Ответ 2

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

 <security:access-denied-handler error-page="/accessDenied"/> - works like charm.

Не забудьте указать обработчик в вашем контроллере:

 @RequestMapping(value = "/accessDenied")
      public String accessDenied() {

            return "accessDenied"; // logical view name
       }

Обновление для Spring Загрузка (2014 Oct):

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.exceptionHandling().accessDeniedHandler(customHandler) OR .accessDeniedPage("/somePage.html").and
            .formLogin()
                .failureHandler(ajaxAuthenticationFailureHandler)} 

В настоящее время мы действительно не возвращаем представления для такой задачи, так как angular js запускается, поэтому вы можете использовать обработчик отказа/успеха и возвращать индивидуальные ответы JSON. Для нас было достаточно использовать обработчик отказа, но вы можете выбрать, где вы хотите, чтобы ваш контроль ударил. Обычно мы не используем разрешающие средства представления, поскольку существуют рамки пользовательского интерфейса (например, angular partials), способные создавать фрагменты в одна страница для вас. Элементы Html хранятся на сервере и служат просто как статические ресурсы.

Позволяет играть с Embedded Tomcat для достижения аналогичного поведения с web.xml!

@Configuration
@EnableAutoConfiguration
public class ApplicationWebXml extends SpringBootServletInitializer {

private static final Logger LOGGER = LoggerFactory.getLogger(Application.class);

@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
    return application.profiles(addDefaultProfile())
            .showBanner(false)
            .sources(Application.class);
}

//required for container customizer to work, the numerous tutorials didn't work for me, so I simply tried overriding the default one
@Bean
public EmbeddedServletContainerFactory servletContainer() {
    TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
    return tomcat;
}

@Bean
public EmbeddedServletContainerCustomizer containerCustomizer(

) {
    return new EmbeddedServletContainerCustomizer() {
        @Override
        public void customize(ConfigurableEmbeddedServletContainer container) {
            TomcatEmbeddedServletContainerFactory containerFactory = (TomcatEmbeddedServletContainerFactory) container;
             containerFactory.setSessionTimeout(1); // just for your interest, remove as necessary

            containerFactory.addErrorPages(new ErrorPage(HttpStatus.FORBIDDEN,"/views/accessDenied.html"),
                    new ErrorPage(HttpStatus.NOT_FOUND,"/views/notFound.html"));
            containerFactory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
                @Override
                public void customize(Connector connector) {
                    connector.setPort(8082);// just for your interest, remove as necessary
                }
            });
        }
    };
}

}

Ответ 3

Более чистый способ обработки переадресации ошибок - использовать теги <error-page> и <error-code> в вашем web.xml. Ниже приведен пример:

<!-- Custom 403 Error Page -->
<!--
            NOTE: Security will throw this error when a user has been authenticated successfully
            but lacks the permissions to perform the requested action.
    -->
    <error-page>
        <error-code>403</error-code>
        <location>/403.jsp</location>
    </error-page>

Этот блок кода будет перенаправляться в указанное место всякий раз, когда он встречает указанный код ошибки.

Это устраняет необходимость в коде авторизации внутри вашей логики приложения.

Ответ 4

Способ выполнения этой работы - определить обработчик в вашей точке входа:

public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, org.springframework.security.core.AuthenticationException authException) throws IOException, ServletException {

        if (authException != null) {
            // you can check for the spefic exception here and redirect like this
            response.sendRedirect("403.html");
        }
    }
}

Вы можете определить это как свою точку входа, установив это как точку входа в файле конфигурации xml:

<http entry-point-ref="customAuthenticationEntryPoint">

  ...

</http>

Ответ 5

Вы проверили тег в приложении, и мне кажется, что он работает.

<sec:access-denied-handler error-page="/handle403Url" />

где handle403Url Я хочу вызвать для обработки этой ошибки (например, чтобы показать ошибку).

Не забывайте, что вы должны разрешить этот URL-адрес в фильтрах, чтобы он мог быть достигнут этим полномочием пользователя, поэтому в начале flters вам нужно добавить что-то вроде этого:

<sec:intercept-url pattern="/handle403Url" filters="none" />