spring security的自定义过滤器实现URL过滤

时间:2025-04-11 14:10:05
spring security的自定义过滤器实现URL过滤

最近要实现一个功能,在使用spring security判断完成权限后,还要验证一下URL是否能访问。
因为spring security是用的正则表达式,比如:
http://localhost/order/?id=13343434
拦截的URL就写成 order/?*,然后定义成为一个“订单”权限赋予用户。但是并不控制,比如这种到数据的关系,比如
id为132434,1343434,13434的这几个只能让部门经理看,id为1343431的只能让创建人看这种需求,要实现这样的需求,我计划的是在权限拦截之后,实现一个自定义的拦截器,调用业务的manager去实现验证。如果通过,向下执行;如果不通过,那么转向到没有数据权限页面。

比较土的办法,不晓得有没有其他好办法,我没有使用到spring security的AnonymousProcessFilter,我们系统内的用户都是要登录的,所以我决定重写这个filter来实现这个URL过滤的功能。

修改配置文件,增加如下内容:
<beans:bean class="">
<custom-filter before="ANONYMOUS_FILTER" />
<beans:property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS" />
<beans:property name="key" value="springsecurity"/>
</beans:bean>

其中的ANONYMOUS_FILTER是告诉spring的filter链,我要在哪个位置加入我的自定义fitler

类如下,目前没有实现正则判断URL,而只是通过URL去匹配,这里还需要稍微改进下:
package ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
public class CustomerAnonymousProcessingFilter extends SpringSecurityFilter
implements InitializingBean {
private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource();
private String key;
private UserAttribute userAttribute;
private boolean removeAfterRequest = true;
public void afterPropertiesSet() throws Exception {
(userAttribute);
(key);
}
protected boolean applyAnonymousForThisRequest(HttpServletRequest request) {
return true;
}
protected Authentication createAuthentication(HttpServletRequest request) {
AnonymousAuthenticationToken auth = new AnonymousAuthenticationToken(
key, (), userAttribute
.getAuthorities());
(authenticationDetailsSource
.buildDetails((HttpServletRequest) request));
return auth;
}

private boolean isJspResources(HttpServletRequest request) {
boolean flag = false;
return flag;
}

protected void doFilterHttp(HttpServletRequest request,
HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
if (() != null
&& ().getAuthentication() != null
&& ().getAuthentication()
.isAuthenticated()) {
//获得前面filter登陆的用户loginId
String loginId = ()
.getAuthentication().getName();
//得到请求URL
String url = ().toLowerCase();
//目前通过properties获得对应的spring bean名称
String managerName = ()
.get(url);
boolean flag = true;
if ((managerName)) {
//要实现资源拦截的manager多implement一个接口ResourceMappingManager
flag = ((ResourceMappingManager) getAppContext(request)
.getBean(managerName)).checkResourceMapping(loginId,
url);
//flag = false; //测试用
if (!flag) {
// 不通过,那么转向没有权限页面
(()
+ "/common/");
return;
}
//放行
}
}
(request, response);
}

protected ApplicationContext getAppContext(HttpServletRequest request) {
HttpSession session = ();
ApplicationContext ctx = WebApplicationContextUtils
.getRequiredWebApplicationContext(());
return ctx;
}
public int getOrder() {
return FilterChainOrder.ANONYMOUS_FILTER;
}
public String getKey() {
return key;
}
public UserAttribute getUserAttribute() {
return userAttribute;
}
public boolean isRemoveAfterRequest() {
return removeAfterRequest;
}
public void setAuthenticationDetailsSource(
AuthenticationDetailsSource authenticationDetailsSource) {
(authenticationDetailsSource,
"AuthenticationDetailsSource required");
= authenticationDetailsSource;
}
public void setKey(String key) {
= key;
}
public void setRemoveAfterRequest(boolean removeAfterRequest) {
= removeAfterRequest;
}
public void setUserAttribute(UserAttribute userAttributeDefinition) {
= userAttributeDefinition;
}
}

用到的类如下,这个是参考同事获得properties文件的工具类写的:
package ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
public class ResourceSystemConfiguration {
private static CompositeConfiguration config;
private static PropertiesConfiguration propertiesConfig;
static {
config = new CompositeConfiguration();
if (propertiesConfig == null) {
try {
propertiesConfig = new PropertiesConfiguration(
"");
propertiesConfig
.setReloadingStrategy(new FileChangedReloadingStrategy());
(propertiesConfig);
} catch (ConfigurationException e) {
();
}
}
}
private ResourceSystemConfiguration() {
}
public static String getString(String propertyKey) {
return (propertyKey);
}
public static String getString(String propertyKey, String defaultValue) {
return (propertyKey, defaultValue);
}
public static int getInt(String propertyKey) {
return (propertyKey);
}
public static int getInt(String key, int defaultValue) {
return (key, defaultValue);
}
public static float getFloat(String propertyKey) {
return (propertyKey);
}
public static float getFloat(String propertyKey, float defaultValue) {
return (propertyKey, defaultValue);
}
public static boolean getBoolean(String propertyKey) {
return (propertyKey);
}
public static boolean getBoolean(String propertyKey, boolean defualtValue) {
return (propertyKey, defualtValue);
}
public static String[] getStringArray(String propertyKey) {
return (propertyKey);
}
public static List<String> getStringList(String propertyKey) {
List<String> list = new ArrayList<String>();
String[] strArr = getStringArray(propertyKey);
for (String value : strArr) {
(value);
}
return list;
}
public static Map<String, String> getResourceMap() {
Iterator<?> itkey = ();
Map<String, String> map = new HashMap<String, String>();
for (; ();) {
String key = (String) ();
String value = (key);
(key, value);
}
return map;
}
@SuppressWarnings("unchecked")
public static List getList(String propertyKey) {
return (propertyKey);
}
}

最后一个如下,以后可以修改为数据库来存放这个对应关系:
/icpmis/user/*=userManager,id
我们的只要实现接口ResourceMappingManager就行了:
public class UserManagerImpl extends BaseManagerImpl<User> implements
UserManager ,ResourceMappingManager
接口里面要各个业务manager实现这个接口就行了,到时候MAPPING的这个FITLER就自动调用各个业务方法的MANAGER来验证是否通过:
package ;
public interface ResourceMappingManager {
public boolean checkResourceMapping(String loginId, String bussinessId);
}