看网上很多人问security中页面隐藏的问题,对于在数据库中自定义资源、角色时标签<sec:authorize url=...> 无法正常使用,有很多人在JSP中想法调用 WebApplicationObjectSupport 或用标签库去解决,实在是繁琐之致,其实很简单的几步就能解决问题,关键就是要自己去覆盖DefaultWebInvocationPrivilegeEvaluator类
1、实现一个WebInvocationPrivilegeEvaluator实现类以替代security框架自动生成的DefaultWebInvocationPrivilegeEvaluator,主要代码如下:
package cn.com.topit.base;
import java.util.Collection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator;
public class TopitWebInvocationPrivilegeEvaluator implements WebInvocationPrivilegeEvaluator {
private final AbstractSecurityInterceptor securityInterceptor;
public TopitWebInvocationPrivilegeEvaluator(AbstractSecurityInterceptor securityInterceptor) {
this.securityInterceptor = securityInterceptor;
}
private static final Logger log = LoggerFactory.getLogger(TopitWebInvocationPrivilegeEvaluator.class);
public boolean isAllowed(String uri, Authentication authentication) {
return isAllowed(null, uri, null, authentication);
}
public boolean isAllowed(String contextPath, String uri, String method, Authentication authentication) {
//FilterInvocation fi = new FilterInvocation(contextPath, uri, method);/若数据库中配置了项目名,如/test/hr/users_manager,则直接使用contextPath,不能设为""
FilterInvocation fi = new FilterInvocation("", uri, method);
Collection<ConfigAttribute> attrs = securityInterceptor.obtainSecurityMetadataSource().getAttributes(fi);
try {
securityInterceptor.getAccessDecisionManager().decide(authentication, fi, attrs);
} catch (AccessDeniedException unauthorized) {
log.info(" denied for " + authentication.toString(), unauthorized);
return false;
}
return true;
}
}
主要就是实现两个方法isAllowed(...),其中contextPath参数大家可以自己测试一下,应该就是项目路径,如我的项目地址为http://localhost:8080/sample,contextPath就是/sample,如果在我们数据库资源表中定义资源时加上了项目路径如 /sample/hr/user_manager,则使用FilterInvocation fi = new FilterInvocation(contextPath, uri, method)即可,因为一般情况大家都只会在记录中这样定义资源 /hr/user_manager,因此只用把contextPath简单的设为""即可。
2,配置文件修改,application-security.xml中的<http auto-config='true' 标签前加上以下代码(一定要在<http auto-config='true' 之前!)
<beans:bean id="topitWebInvocationPrivilegeEvaluator"
class="cn.com.topit.base.TopitWebInvocationPrivilegeEvaluator">
<beans:constructor-arg name="securityInterceptor"
ref="topitFilter" />
</beans:bean>
//bean id的名字无所谓,topitFilter引用的是自己实现的AbstractSecurityInterceptor
重启服务,大家试试吧!
你不知道AbstractSecurityInterceptor?网上查查吧,大把资料,还不明白的话留言吧