例如,我有:
<intercept-url pattern="/aaa/**" access="ROLE_AAA" />
<intercept-url pattern="/bbb/**" access="ROLE_BBB" />
因此,如果用户想要页面/ aaa并且同时没有角色ROLE_AAA - 我想让他重定向到page / access-denied-aaa /
并且,如果他试图获得/ bbb且没有ROLE_BBB - > to page / access-denied-bbb /。
目前我只能描述一个AccessDeniedHandler,它有一个共同的accessDenied页面......
通常如何实施?最好使用Spring Security
答案 0 :(得分:6)
您始终可以实施自己的AccessDeniedHandler
。这是我通过扩展默认AccessDeniedHandlerImpl
(省略了包和导入)所做的一个例子:
public class PageByResourceAccessDeniedHandler extends AccessDeniedHandlerImpl {
//~ Instance fields ===================================
/**A Map of Path by Error Page*/
private Map<String, String> errorPagesByPaths;
/**The default error page if any of {@link #errorPagesByRole} matches */
private String defaultErrorPage;
//~ Main Methods ======================================
@Override
public void handle(HttpServletRequest request,
HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException,
ServletException {
String errorPage = determineErrorPage(request);
setErrorPage(errorPage);
super.handle(request, response, accessDeniedException);
}
/**
* Searches into the property {@link #errorPagesByRole} for a matching error page
* for the current denied request path.
* @param request current request
* @return a matching error page found in {@link #errorPagesByRole} or {@link #defaultErrorPage}
* if none was found.
*/
private String determineErrorPage(HttpServletRequest request) {
AntPathMatcher apm = new AntPathMatcher();
for (String key : errorPagesByPaths.keySet()) {
if(apm.match(key, request.getServletPath())) {
return errorPagesByPaths.get(key);
}
}
return defaultErrorPage;
}
//~ Getters/Setters/Utilities =========================
public void setErrorPagesByPaths(Map<String, String> errorPagesByPaths) {
for (String key : errorPagesByPaths.keySet()) {
validateErrorPage(errorPagesByPaths.get(key));
}
this.errorPagesByPaths = errorPagesByPaths;
}
public void setDefaultErrorPage(String errorPage) {
validateErrorPage(errorPage);
this.defaultErrorPage = errorPage;
}
/**
* Simple validator based on {@link AccessDeniedHandlerImpl#setErrorPage(String)}
* code. Just verifies if the page doesn't starts with <tt>/</tt>.
*
* @throws IllegalArgumentException if the errorPage doesn't starts with <tt>/</tt>.
*/
private void validateErrorPage(String errorPage) {
if ((errorPage != null) && !errorPage.startsWith("/")) {
throw new IllegalArgumentException("errorPage " + errorPage + " must begin with '/'");
}
}
}
以下是在应用程序上下文配置文件中配置它的方法:
<bean id="pbrADH" class="com.foo.PageByResourceAccessDeniedHandler">
<property name="defaultErrorPage" value="/errorpagedefault.jsp" />
<property name="errorPagesByPaths">
<map>
<entry key="/aaa/**" value="/errorpageaaa.jsp" />
<entry key="/bbb/**" value="/errorpagebbb.jsp" />
</map>
</property>
</bean>
不要忘记告诉Spring Security在http
部分中使用它:
...
<http auto-config="true">
<access-denied-handler ref="pbrADH" />
...
</http>
首先,请记住:这只是一个想法。它有效,但可以改进。
基本上它有一个Map,其中键是受保护的资源,值是它们的错误页面。它有一个默认值
它使用AntPathMatcher
来确定当前请求的错误页面,因此您通常可以使用ant路径。在确定错误页面是什么之后,该类只调用它的超类handle
的RoleVoter
方法。
配置它的更好方法是:
AccessDeniedHandlerImpl
但我无法找到一种方法来了解用户没有导致错误的角色。如果您查看{{3}}代码,则可以看到此信息已丢失。