关闭

springsecurity2.0.6代码分析成果

185人阅读 评论(0) 收藏 举报

之前也试着玩过springsecurity,这回把它搬到项目中,却遇到了意想不到的麻烦。我定义了一些角色与资源,下表显示了它们的情况:

 

Loginer        Role                     Resource                    Description

admin          ROLE_ADMIN        /*/*.action                   能访问所有的action资源

user             ROLE_USER          /index/index.action       仅能访问去首页的那个action

 

假设登录后就访问/index/index.action。我的目的是以admin登录的用户,它具有管理者的角色,并能访问所有的action资源;而以user登录的用户只能访问去首页的那个action资源。所以无论谁登录,都应该可以访问 /index/index.action资源。结果只有其中一个能成功!

 

先看一下用于判断是否有权限访问资源的那个类及相关代码:

package org.springframework.security.intercept.web;

....

public class DefaultFilterInvocationDefinitionSource implements FilterInvocationDefinitionSource {

....

    private ConfigAttributeDefinition lookupUrlInMap(Map requestMap, String url) {
        Iterator entries = requestMap.entrySet().iterator();

        while (entries.hasNext()) {
            Map.Entry entry = (Map.Entry) entries.next();
            Object p = entry.getKey();    //这个相当于Resource
            boolean matched = urlMatcher.pathMatchesUrl(p, url);

            if (logger.isDebugEnabled()) {
                logger.debug("Candidate is: '" + url + "'; pattern is " + p + "; matched=" + matched);
            }

            if (matched) {

                //如果用户访问的资料与requestMap内定义的Resource匹配,就返回这个资源对应的所有角色。

               //因为while循环,并且找到匹配后就返回,所以就永远只返回第一条匹配的Resource对应的所有角色了。

                return (ConfigAttributeDefinition) entry.getValue(); ****(1)
            }
        }

        return null;
    }

....

}

 

 

package org.springframework.security.vote;

....

  public class RoleVoter implements AccessDecisionVoter {

....

    public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) {
        int result = ACCESS_ABSTAIN;
        Iterator iter = config.getConfigAttributes().iterator();    //此迭代器的内容就是上边返回的匹配与当前请求的所有角色
        GrantedAuthority[] authorities = extractAuthorities(authentication);    //当前登录者拥有的所有角色

        while (iter.hasNext()) {
            ConfigAttribute attribute = (ConfigAttribute) iter.next();    //迭代器里的每个角色

            if (this.supports(attribute)) {
                result = ACCESS_DENIED;

                //如果当前登录都其中一个角色与当前请求匹配的其中一个角色对应,就允许访问。

                ****(2)
                for (int i = 0; i < authorities.length; i++) {
                    if (attribute.getAttribute().equals(authorities[i].getAuthority())) {

 

                        return ACCESS_GRANTED;
                    }
                }
            }
        }
        return result;
    }

....

  }

 

所以,结论如下:

在(1)处,如果第一条匹配的Resource对应的角色是ROLE_ADMIN,用user来登录的话,虽然他能够访问 /index/index.action,但user的角色是ROLE_USER,所以(2)处作判断的话就说他没权限访问了;

在(1)处,如果第一条匹配的Resource对应的角色是ROLE_USER,用admin来登录的话,虽然他能够访问 /index/index.action,但admin的角色是ROLE_ADMIN,所以(2)处作判断的话就说他没权限访问了。

 

最后的教训是,在定义资源的时候,不同的资源必须互不相干,如果象我上边那样一个资源能匹配另一个,就会出现无权访问资源的后果了。

 

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:30716次
    • 积分:524
    • 等级:
    • 排名:千里之外
    • 原创:20篇
    • 转载:0篇
    • 译文:0篇
    • 评论:25条
    文章分类
    最新评论