Acegi中的FilterInvocationDefinitionMap的局限性及小改进

Acegi中的FilterInvocationDefinitionMap提供两种实现:PATTERN_TYPE_ANT_PATH及PATTERN_TYPE_PERL5。其中PATTERN_TYPE_ANT_PATH使用apache Ant的路径格式来进行url的模式匹配,由于只有**, *, ?少数几个通配符,所以使用起来比较简单,但是无法支持带参数的url,如/action.do?method=m这种url,在进行匹配之前,会先将?后面的部分截去。见PathBasedFilterInvocationDefinitionMap.java的代码:
java 代码
 
  1. public ConfigAttributeDefinition lookupAttributes(String url) {  
  2.     // Strip anything after a question mark symbol, as per SEC-161. See also SEC-321  
  3.     int firstQuestionMarkIndex = url.indexOf("?");  
  4.   
  5.     if (firstQuestionMarkIndex != -1) {  
  6.         url = url.substring(0, firstQuestionMarkIndex);  
  7.     }  
  8.   
  9.     if (isConvertUrlToLowercaseBeforeComparison()) {  
  10.         url = url.toLowerCase();  
  11.   
  12.         if (logger.isDebugEnabled()) {  
  13.             logger.debug("Converted URL to lowercase, from: '" + url + "'; to: '" + url + "'");  
  14.         }  
  15.     }  
  16.   
  17.     Iterator iter = requestMap.iterator();  
  18.   
  19.     while (iter.hasNext()) {  
  20.         EntryHolder entryHolder = (EntryHolder) iter.next();  
  21.   
  22.         boolean matched = pathMatcher.match(entryHolder.getAntPath(), url);  
  23.   
  24.         if (logger.isDebugEnabled()) {  
  25.             logger.debug("Candidate is: '" + url + "'; pattern is " + entryHolder.getAntPath() + "; matched="  
  26.                 + matched);  
  27.         }  
  28.   
  29.         if (matched) {  
  30.             return entryHolder.getConfigAttributeDefinition();  
  31.         }  
  32.     }  
  33.   
  34.     return null;  
  35. }  
在对Acegi的缺省实现不进行扩展的情况下,要实现对带参数URL的安全控制,可以使用PATTERN_TYPE_PERL5即正则表达式进行模式匹配(在RegExpBasedFilterInvocationDefinitionMap中实现),例如上述的路径可以用如下的模式来进行匹配:^/user\.do\?method=.*,采用这种方案的优点是可以利用正则表达式的强大表达能力,缺点是难以实现模式的自动生成。在一个实用的基于角色的权限管理体系中,通常对要进行安全控制的资源是由管理员通过管理界面来定制的,如果使用PATTERN_TYPE_PERL5的格式来制定模式,则需要管理员熟练掌握正则表达式的使用,有难度。考虑实现一个UrlFilterInvocationDefinitionMap,仅提供一种通配符*,又支持url参数,简单又实用。代码如下:
java 代码
 
  1. import org.acegisecurity.ConfigAttributeDefinition;  
  2. import org.acegisecurity.intercept.web.AbstractFilterInvocationDefinitionSource;  
  3. import org.acegisecurity.intercept.web.FilterInvocationDefinition;  
  4. import org.apache.commons.logging.Log;  
  5. import org.apache.commons.logging.LogFactory;  
  6.   
  7. import java.util.*;  
  8.   
  9. /** 
  10.  * User: user 
  11.  * Date: 2007-4-11 
  12.  * Time: 9:14:00 
  13.  */  
  14. public class UrlFilterInvocationDefinitionMap extends AbstractFilterInvocationDefinitionSource  
  15.     implements FilterInvocationDefinition {  
  16.   
  17.     private static final Log logger = LogFactory.getLog(UrlFilterInvocationDefinitionMap.class);  
  18.   
  19.     private List<EntryHolder> requestMap = new ArrayList<EntryHolder>();  
  20.     private boolean convertUrlToLowercaseBeforeComparison = false;  
  21.   
  22.     public ConfigAttributeDefinition lookupAttributes(String url) {  
  23.         Iterator iter = requestMap.iterator();  
  24.   
  25.         if (isConvertUrlToLowercaseBeforeComparison()) {  
  26.             url = url.toLowerCase();  
  27.   
  28.             if (logger.isDebugEnabled()) {  
  29.                 logger.debug("Converted URL to lowercase, from: '" + url + "'; to: '" + url + "'");  
  30.             }  
  31.         }  
  32.   
  33.         while (iter.hasNext()) {  
  34.             EntryHolder entryHolder = (EntryHolder) iter.next();  
  35.   
  36.             boolean matched = UrlMatcher.matches(url, entryHolder.getUrlPattern());  
  37.   
  38.             if (logger.isDebugEnabled()) {  
  39.                 logger.debug("Candidate is: '" + url + "'; pattern is " + entryHolder.getUrlPattern()  
  40.                     + "; matched=" + matched);  
  41.             }  
  42.   
  43.             if (matched) {  
  44.                 return entryHolder.getConfigAttributeDefinition();  
  45.             }  
  46.         }  
  47.   
  48.         return null;  
  49.     }  
  50.   
  51.     public Iterator getConfigAttributeDefinitions() {  
  52.         Set<ConfigAttributeDefinition> set = new HashSet<ConfigAttributeDefinition>();  
  53.         for (EntryHolder aRequestMap : requestMap) {  
  54.             set.add(aRequestMap.getConfigAttributeDefinition());  
  55.         }  
  56.         return set.iterator();  
  57.     }  
  58.   
  59.     public void addSecureUrl(String urlPattern, ConfigAttributeDefinition attr) {  
  60.         requestMap.add(new EntryHolder(urlPattern, attr));  
  61.   
  62.         if (logger.isDebugEnabled()) {  
  63.             logger.debug("Added url pattern: " + urlPattern + "; attributes: " + attr);  
  64.         }  
  65.     }  
  66.   
  67.     public boolean isConvertUrlToLowercaseBeforeComparison() {  
  68.         return this.convertUrlToLowercaseBeforeComparison;    
  69.     }  
  70.   
  71.     public void setConvertUrlToLowercaseBeforeComparison(boolean convertUrlToLowercaseBeforeComparison) {  
  72.         this.convertUrlToLowercaseBeforeComparison = convertUrlToLowercaseBeforeComparison;  
  73.     }  
  74.   
  75.     protected class EntryHolder {  
  76.         private ConfigAttributeDefinition configAttributeDefinition;  
  77.         private String urlPattern;  
  78.   
  79.         public EntryHolder(String urlPattern, ConfigAttributeDefinition attr) {  
  80.             this.urlPattern = urlPattern;  
  81.             this.configAttributeDefinition = attr;  
  82.         }  
  83.   
  84.         protected EntryHolder() {  
  85.             throw new IllegalArgumentException("Cannot use default constructor");  
  86.         }  
  87.   
  88.         public String getUrlPattern() {  
  89.             return urlPattern;  
  90.         }  
  91.   
  92.         public ConfigAttributeDefinition getConfigAttributeDefinition() {  
  93.             return configAttributeDefinition;  
  94.         }  
  95.     }  
  96.   
  97. }  
其中模式匹配用了一个UrlMatcher类,代码及test列在下面:
java 代码
 
  1. import java.util.regex.Pattern;  
  2. import java.util.regex.Matcher;  
  3.   
  4. /** 
  5.  * User: user 
  6.  * Date: 2007-4-11 
  7.  * Time: 9:48:09 
  8.  */  
  9. public class UrlMatcher {  
  10.     public static boolean matches(String url, String urlPattern){  
  11.         StringBuffer buff = new StringBuffer();  
  12.         buff.append('^');  
  13.         buff.append(urlPattern.replaceAll("\\.""\\\\.").replaceAll("\\?""\\\\?").replaceAll("\\*"".*"));  
  14.         buff.append("$");  
  15.         Pattern pattern = Pattern.compile(buff.toString());  
  16.         Matcher matcher = pattern.matcher(url);  
  17.         boolean found = matcher.find();  
  18.         return found && matcher.group().equals(url);  
  19.     }  
  20. }  

java 代码
 
  1. /** 
  2.  * User: user 
  3.  * Date: 2007-4-11 
  4.  * Time: 10:07:07 
  5.  */  
  6.   
  7. import junit.framework.*;  
  8. import com.vnv.basicacegi.security.UrlMatcher;  
  9.   
  10. public class UrlMatcherTest extends TestCase {  
  11.   
  12.     public void testMatches() throws Exception {  
  13.         assertTrue(UrlMatcher.matches("/user.do?method=home""/user.do?method=*"));  
  14.         assertTrue(UrlMatcher.matches("/user/home/abc/action.do""/user/*/action.do"));  
  15.         assertTrue(UrlMatcher.matches("/user/home/abc/action.do?method=a&c=d""/user/*/action.do*"));  
  16.         assertTrue(UrlMatcher.matches("/user/home/abc/action.do?method=a&c=d""/user/*/action.do?*"));  
  17.         assertTrue(UrlMatcher.matches("/user/home/abc/action.do?method=a&c=d""/user/*/action.do?method=*"));  
  18.         assertFalse(UrlMatcher.matches("/user/action.do?method=a&c=d""/user/*/action.do?method=*"));  
  19.         assertTrue(UrlMatcher.matches("/action.do?method=a&c=d""*/action.do?method=*"));  
  20.     }  
  21. }
这下可以爽了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值