我在使用Spring Security 3.0.x时遇到了一个小问题(特别是3.0.2)。我正在处理的整个应用程序工作正常,除非有权限的人试图登录。
当它发生时,用户被重定向到“欢迎”页面,因为他的用户名/密码有效,并且他收到一个可爱的白页,其中包含:“错误403:访问被拒绝”
所以,我一直在网上试图找到如何处理这种行为。到目前为止,我已经得出结论,如果我错了,请纠正我,它由ExceptionTranslationFilter管理。但我不太明白如何善用这些信息。
我已经尝试编辑我的SecurityContext.xml,将 access-denied-handler 标记添加到我的 http 标记中,但它不起作用。我是否需要添加超过此标签才能使其正常工作?还有其他可能性使我的应用程序更加用户友好吗?
修改:我想重定向到一个页面,例如,让我们说403.html。
真诚地,
感谢
答案 0 :(得分:22)
我仍然不明白为什么你必须实现自己的访问处理程序......我目前面临同样的任务:
<security:access-denied-handler error-page="/accessDenied"/> - works like charm.
不要忘记在Controller中指定处理程序:
@RequestMapping(value = "/accessDenied")
public String accessDenied() {
return "accessDenied"; // logical view name
}
Spring Boot更新(2014年10月):
@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响应。对我们来说,使用失败处理程序就足够了,但是您可以选择控件的位置。我们通常不使用视图解析器,因为有一些UI切片框架(例如角度分割)能够将碎片构建到单个页面中为了你。 Html片段存储在服务器上,只是作为静态资源提供。
让我们使用嵌入式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
}
});
}
};
}
}
答案 1 :(得分:9)
处理错误重定向的更简洁方法是使用web.xml中的<error-page>
和<error-code>
标记。请参阅下面的示例:
<!-- 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>
只要遇到指定的错误代码,此代码块就会重定向到指定的位置。
这样就无需在应用程序逻辑中使用授权代码。
答案 2 :(得分:8)
我发现了如何做到这一点。通过实现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 -->
答案 3 :(得分:3)
使这项工作的方法是在入口点定义一个处理程序:
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>
答案 4 :(得分:1)
您已经检查了应用程序中的标记,对我来说它似乎有效。
<sec:access-denied-handler error-page="/handle403Url" />
我想调用handle403Url来处理此错误(例如显示错误)。
不要忘记您必须在过滤器中允许此URL,以便此用户权限可以访问它,因此在flters的开头您必须添加以下内容:
<sec:intercept-url pattern="/handle403Url" filters="none" />