首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

关于spring security的URL路径验证有关问题

2012-10-06 
关于spring security的URL路径验证问题在前一篇文章中,还是有些地方没讲清楚,但那篇文章已经有点长了,所以

关于spring security的URL路径验证问题
在前一篇文章中,还是有些地方没讲清楚,但那篇文章已经有点长了,所以还是另外单独讲一下吧。见SecureResourceFilterInvocationDefinitionSource代码:

/** * RegexUrlPathMatcher默认不进行小写转换,而AntUrlPathMatcher默认要进行小写转换 */    public void afterPropertiesSet() throws Exception {                // default url matcher will be RegexUrlPathMatcher        this.urlMatcher = new RegexUrlPathMatcher();                if (useAntPath) {  // change the implementation if required            this.urlMatcher = new AntUrlPathMatcher();        }                // Only change from the defaults if the attribute has been set        if ("true".equals(lowercaseComparisons)) {            if (!this.useAntPath) {                ((RegexUrlPathMatcher) this.urlMatcher).setRequiresLowerCaseUrl(true);            }        } else if ("false".equals(lowercaseComparisons)) {            if (this.useAntPath) {            //是否对URL全部转换成小写格式                ((AntUrlPathMatcher) this.urlMatcher).setRequiresLowerCaseUrl(false);            }        }            }//这个方法主要会在FilterSecurityInterceptor->AbstractSecurityInterceptor->beforeInvocation中用到    public ConfigAttributeDefinition getAttributes(Object filter) throws IllegalArgumentException {                FilterInvocation filterInvocation = (FilterInvocation) filter;        String requestURI = filterInvocation.getRequestUrl();        Map<String, String> urlAuthorities = this.getUrlAuthorities(filterInvocation);                String grantedAuthorities = null;        for(Iterator<Map.Entry<String, String>> iter = urlAuthorities.entrySet().iterator(); iter.hasNext();) {            Map.Entry<String, String> entry = iter.next();                        //url表示从资源表取出的值,在这里代表的是相应的URL            String url = entry.getKey();                        //这段代码表示数据库内的需要验证的资源URL与当前请求的URL相匹配时进行验证            if(urlMatcher.pathMatchesUrl(url, requestURI)) {            //grantedAuthorities表示每个资源对应的角色,如果有多个角色,则以','隔开                grantedAuthorities = entry.getValue();                break;            }        }                if(grantedAuthorities != null) {            ConfigAttributeEditor configAttrEditor = new ConfigAttributeEditor();            configAttrEditor.setAsText(grantedAuthorities);            return (ConfigAttributeDefinition) configAttrEditor.getValue();        }                //返回null表示不会验证        return null;    }


这个方法的主要作用是从数据库的resource表加载出所有的资源URL值,通过它与request请求的URL相比较,而比较器一般采用AntUrlPathMatcher,如果需要更加灵活的方式,可以使用RegexUrlPathMatcher,先介绍一下上面的getAttributes是怎么通过URL进行验证的。从上面的for循环可以看出,首先遍历资源URL的列表,如果发现有与当前request请求URL相匹配的,就进行验证,如果当前用户拥有的角色与此资源URL对应的角色相同,则通过验证,否则禁止访问。见下图:



上面一张简单的图,基本能说明意思,需要说明的是只要发现有与当前请求路径相匹配的,就会进行验证,而且只验证一次,没有通过验证也不会再检查是否匹配第二个资源URL,的当然如果请求的URL与第一个资源URL不匹配,就会继续向下查找,直到找到与请求URL匹配的资源URL为止,如果遍历完以后,还是没有查到,就到弃权处理,至于所有投票者都弃权以后,该怎么处理,前一篇博客有介绍的。由此可知,这个资源的URL路径的顺序就比较重要了。如果遍历出来的第一个资源URL为/**,而普通用户角色对应的资源URL没有它,那么即使普通角色拥有其它的资源URL权限也是不能访问到相应的页面的。但是如果普通用户有/**的权限,而/**是匹配所有路径的,如/admin/index.jsp也是会匹配的,这样就相当于普通用户拥有任何路径的权限,这也是不行的。所以遍历出来的资源URL顺序很重要。

在基于XML的方式授权时就是把/**放在最后面的,如:

<intercept-url pattern="/secure/extreme/**" access="ROLE_SUPERVISOR"/>        <intercept-url pattern="/secure/**" access="IS_AUTHENTICATED_REMEMBERED" />        <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />


也就是说,这个路径放的顺序很重要,在数据库里存放URL时也要遵循这样的规则,如上面的XML放在数据库里应该这样:



这里需要多做的一个步骤是,取出来后不要改变取数据库记录的顺序。在SecurityManagerSupport中的代码:

public Map<String, String> loadUrlAuthorities() {        Map<String, String> urlAuthorities = new LinkedHashMap<String, String>();                @SuppressWarnings("unchecked")        List<Resource> urlResources = getHibernateTemplate().find("FROM Resource resource WHERE resource.type = ?", "URL");        for(Resource resource : urlResources) {            urlAuthorities.put(resource.getValue(), resource.getRoleAuthorities());        }        return urlAuthorities;    }


要保持取出的数据的顺序不改变,需要使用LinkedHashMap,这样SecureResourceFilterInvocationDefinitionSource在验证URL的顺序就与数据库里面存的顺序一致了,表面上看的确有些不灵活,而实际上,在使用中时资源URL是固定的,用户不能改变的,所以这也没什么影响。

关于AntUrlPathMatcher的匹配规则也很简单,文档中有说明:

 * <li>? matches one character</li> * <li>* matches zero or more characters</li> * <li>** matches zero or more 'directories' in a path</li>

热点排行