如何使用 Spring Security 3.0.x 处理 HTTP 403
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4186697/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to handle HTTP 403 with Spring Security 3.0.x
提问by ALOToverflow
I'm facing a little issue with Spring Security 3.0.x (3.0.2 in particular at the moment). The whole application I'm working on is working perfectly except when someone who doesn't have the authorities tries to log on.
我在 Spring Security 3.0.x(特别是现在的 3.0.2)方面遇到了一个小问题。我正在处理的整个应用程序运行良好,除非有人没有权限尝试登录。
When it occurs, the users is redirected to the "welcome" page, since his username/password are valid, and he receive a cute white page with this : "Error 403: Access is denied"
当它发生时,用户被重定向到“欢迎”页面,因为他的用户名/密码是有效的,他会收到一个可爱的白色页面:“错误 403:访问被拒绝”
So, I've been looking on the net trying to find how this behavior can be handled. So far I've come to the conclusion, please correct me if I'm wrong, that it is managed by the ExceptionTranslationFilter. But I don't quite understand how to make any good use of this information.
所以,我一直在网上寻找,试图找到如何处理这种行为。到目前为止,我得出的结论是,如果我错了,请纠正我,它是由ExceptionTranslationFilter管理的。但我不太明白如何充分利用这些信息。
I've tryied to edit my SecurityContext.xml to add a access-denied-handlertag to my httptag, but it doesn't work. Do I need to add more than this tag to make it work? Is there any other possibilities to make my application more user-friendly?
我已经尝试编辑我的 SecurityContext.xml 以将访问拒绝处理程序标记添加到我的http标记,但它不起作用。我需要添加比这个标签更多的标签才能使其工作吗?是否还有其他可能性可以使我的应用程序更加用户友好?
Edit: I would like to redirect to a page, let's says 403.html, for example.
编辑:我想重定向到一个页面,例如 403.html。
Sincerly,
Thanks
真诚的,
谢谢
采纳答案by ALOToverflow
I've found how to do this. By implementing the AccessDeniedHandlerinterface and the corresponding handle method I can, easily, control the way the Http 403 error is handled.
我已经找到了如何做到这一点。通过实现AccessDeniedHandler接口和相应的句柄方法,我可以轻松控制 Http 403 错误的处理方式。
This way, you can add various items in the session and then intercept them on your jsp.
这样,你就可以在会话中添加各种项目,然后在你的jsp上拦截它们。
The xml file then looks like this :
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>
The java class :
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;
}
}
And a jsp example :
和一个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 -->
回答by Aubergine
I still don't get why you had to implement your own access handler... I have currently faced same task:
我仍然不明白为什么你必须实现自己的访问处理程序......我目前面临着同样的任务:
<security:access-denied-handler error-page="/accessDenied"/> - works like charm.
Don't forget to specify handler in your Controller:
不要忘记在您的控制器中指定处理程序:
@RequestMapping(value = "/accessDenied")
public String accessDenied() {
return "accessDenied"; // logical view name
}
Update for Spring Boot(2014 Oct):
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)}
Nowadays we don't really return views for such task since angular js kicks in so you can use your failure/success handler and return tailored JSON responses. For us it was sufficient to use failure handler but you get to choose where you want your control to kick in. We generally don't use view resolvers as there are UI tiles frameworks(such as angular partials) able to construct pieces into single page for you. Html pieces are stored on the server and served simply as static resources.
现在我们并没有真正返回此类任务的视图,因为 angular js 开始使用,因此您可以使用失败/成功处理程序并返回定制的 JSON 响应。对我们来说,使用失败处理程序就足够了,但您可以选择您希望控件启动的位置。我们通常不使用视图解析器,因为有 UI 平铺框架(例如 angular partials)能够将片段构建到单个页面中为你。Html 片段存储在服务器上,仅用作静态资源。
Lets play with Embedded Tomcat to achieve similar behavior to web.xml !
让我们使用嵌入式 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
}
});
}
};
}
}
}
回答by Kristen D.
A cleaner way to handle error redirects is to use the <error-page>and <error-code>tags in your web.xml. See below for an example:
处理错误重定向的一种更简洁的方法是在 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>
This block of code will redirect to the specified location whenever it encounters the specified error code.
每当遇到指定的错误代码时,此代码块将重定向到指定的位置。
This eliminates the need for authorization code inside your application logic.
这消除了在应用程序逻辑中使用授权代码的需要。
回答by Grant Cermak
The way to make this work is to define a handler in your entry point:
完成这项工作的方法是在入口点定义一个处理程序:
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");
}
}
}
You can define this as your entry point by setting this as you entry point in the xml config file:
您可以通过将其设置为 xml 配置文件中的入口点来将其定义为入口点:
<http entry-point-ref="customAuthenticationEntryPoint">
...
</http>
回答by Javi
You have checked the tag in an application and to me it seems to work.
您已经检查了应用程序中的标签,对我来说它似乎有效。
<sec:access-denied-handler error-page="/handle403Url" />
where handle403Url I want to call to handle this error (for example to show an error).
我想调用 handle403Url 来处理这个错误(例如显示错误)。
Don't forget that you have to allow this url in the filters so it can be reached by this user authority, so in the start of the flters you have to add something like this:
不要忘记,您必须在过滤器中允许此 url,以便此用户权限可以访问它,因此在过滤器的开头,您必须添加如下内容:
<sec:intercept-url pattern="/handle403Url" filters="none" />

