弄这个框架的时候,因为这个问题困扰了很久,一直显示无法进入AccessDecisionManager内,导致资源请求无法进行有效拦截,资料找了很久也并未找到合理解决方案,表示当时就脑子不够用,及看不懂源码,又不懂原理,搭建都是靠人家的教程,一开始也看到了一篇类似的博文,但没太在意,事实证明也正是因为那个原因导致,
博文内容如下:
原文地址:http://blog.163.com/jiawei28888@126/blog/static/799737692015217103427362/
随后,根据此提示修改了相应代码,
@Override
public Collection<ConfigAttribute> getAttributes(Object obj)
throws IllegalArgumentException {
// TODO Auto-generated method stub
//获取请求的url地址
String url = ((FilterInvocation)obj).getRequestUrl();
System.out.println("FilterInvocationSecurityMetadataSourceImpl:getAttributes()---------------请求地址为:"+url);
Collection<ConfigAttribute> collection = new LinkedList<>();
//查询数据库中是否存在此链接
List<ModuleApRole> moduleApRoleList = moduleMapper.selectByUri(url);
for (ModuleApRole moduleApRole : moduleApRoleList) {
if (moduleApRole.getRole_id() != null) {
ConfigAttribute configAttribute = new SecurityConfig(moduleApRole.getRole_id()+"");
collection.add(configAttribute);
}
}
//防止数据库中没有数据,不能进行权限拦截
if(collection.size()<1){
ConfigAttribute configAttribute = new SecurityConfig("ROLE_NO_USER");
collection.add(configAttribute);
}
return collection;
}
这样框架在解析的时候就会判断此请求有效,然后再进入AccessDecisionManager的decide()进行资源权限的验证,实测是可以的,还有一种方法听说是重写AbstractSecurityInterceptor的方法实现。至于为什么collection在返回的时候不能为空,那不管,那是框架定的规则。
还有一种,是资源拦截不准确,可能出现的情况有如下两种情况:
- 1.使用了Struts2+spring框架,在web.xml文件,<filter>标签时 Struts2配置到了spring security上面,由于web.xml配置文件中执行顺序是从上至下,所以可能会导致资源请求时被Struts2先拦截,
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>adsystem</display-name>
<welcome-file-list>
<welcome-file>wrt/manage/main.jsp</welcome-file>
</welcome-file-list>
<!-- Spring 配置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml,classpath:applicationContext-Security.xml,classpath:applicationContext-mybatis.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Spring 刷新Introspector防止内存泄露 -->
<listener>
<listener-class>
org.springframework.web.util.IntrospectorCleanupListener
</listener-class>
</listener>
<!-- 防止多人登陆 ,控制一个用户只能登录一次,不能在其他地方重新登录-->
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>
<!-- session超时定义,单位为分钟 -->
<session-config>
<session-timeout>20</session-timeout>
</session-config>
<!-- Struts2配置 使用默认-->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
<!-- Spring Security 安全管理机制 -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 配置log4j配置文件的路径,可以是xml或 properties(此参数必须配)-->
<!-- 下面使用了classpath 参数指定log4j.properties文件的位置,这样log4j的配置文件就不用非要放到src的下面 -->
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:config/log4j.properties</param-value>
</context-param>
<!-- 使用spring的监听器,当应用启动时来读取log4j的配置文件 -->
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
</web-app>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>adsystem</display-name>
<welcome-file-list>
<welcome-file>wrt/manage/main.jsp</welcome-file>
</welcome-file-list>
<!-- Spring 配置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml,classpath:applicationContext-Security.xml,classpath:applicationContext-mybatis.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Spring 刷新Introspector防止内存泄露 -->
<listener>
<listener-class>
org.springframework.web.util.IntrospectorCleanupListener
</listener-class>
</listener>
<!-- 防止多人登陆 ,控制一个用户只能登录一次,不能在其他地方重新登录-->
<listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher
</listener-class>
</listener>
<!-- session超时定义,单位为分钟 -->
<session-config>
<session-timeout>20</session-timeout>
</session-config>
<!-- Spring Security 安全管理机制 -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Struts2配置 使用默认-->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
<!-- 配置log4j配置文件的路径,可以是xml或 properties(此参数必须配)-->
<!-- 下面使用了classpath 参数指定log4j.properties文件的位置,这样log4j的配置文件就不用非要放到src的下面 -->
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:config/log4j.properties</param-value>
</context-param>
<!-- 使用spring的监听器,当应用启动时来读取log4j的配置文件 -->
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
</web-app>
- 资源不能被拦截,配置属于失效情况,可能是在applicationContext-Security.xml配置文件中,忘了将安全访问策略配置上去,<security:custom-filter ref="myFilterSecurityInterceptor" before="FILTER_SECURITY_INTERCEPTOR"/>