SpringSecurity3.X权限原理

这里给出一个简单的安全验证的实现例子,先说一下需求:

1.通过登录页面进行登录

2.用户登录前访问被保护的地址时自动跳转到登录页面

3.用户信息存储在数据表中

4.用户权限信息存在在数据表中

5.用户登录成功后访问没有权限访问的地址时跳转到登录页面

 

ok,以上就是一个基本的需求了,大部分的系统都是基于该需求实现登录模块的。

 

给出实现之前,先简单说明一下springsecurity的原理,

1.AccessDecisionManager

和我们一般实现登录验证采用filter的方式一样,springsecurity也是一个过滤器,当请求被springsecurity拦截后,会先对用户请求的资源进行安全认证,如果用户有权访问该资源,则放行,否则将阻断用户请求或提供用户登录,

在springsecurity中,负责对用户的请求资源进行安全认证的是AccessDecisionManager,它就是一组投票器的集合,默认的策略是使用一个AffirmativeBased,既只要有一个投票器通过验证就允许用户访问,

所以如果希望实现自己的权限验证策略,实现自己的投票器是一个很好的选择。

 

2.UserDetailsService

如果用户没有登录就访问某一个受保护的资源,则springsecurity会提示用户登录,用户登录后,由UserDetailsService来验证用户是否合法,既验证用户名和密码是否正确,同时验证用户是否具备相应的资源权限,

即对应的access的value。

如果用户验证通过,则由AccessDecisionManager来决定是否用户可以访问该资源。

 

下面给出具体实现:

web.xml

基本上都是这样配置,就不废话了。

<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 > *.do*"   access = "HODLE"   />   
        <logout   logout-url = "/logout.do"   invalidate-session = "true"   
            logout-success-url = "/logout.jsp"   />   
        <form-login   login-page = "/index.do"   default-target-url = "/frame.do"   
            always-use-default-target = "true"   authentication-failure-url = "/index.do?login_error=1"   />   
        <session-management >   
            <concurrency-control   max-sessions = "1"   />   
        </session-management >   
    </http >   
       
    <beans:bean id = "loggerListener"   
        class = "org.springframework.security.authentication.event.LoggerListener"   />   
  
          
    <authentication-manager >   
        <authentication-provider   user-service-ref = "userService" >   
            <password-encoder   hash = "md5"   />   
        </authentication-provider >   
    </authentication-manager >   
  
    <beans:bean   id = "userService"   class = "com.piaoyi.common.security.UserService"   />   
             
    <beans:bean   id = "accessDecisionManager"   
        class = "org.springframework.security.access.vote.AffirmativeBased" >   
        <beans:property   name = "decisionVoters" >   
            <beans:list >   
                <beans:bean   class = "org.springframework.security.access.vote.RoleVoter"   />   
                <beans:bean   
                    class = "org.springframework.security.access.vote.AuthenticatedVoter"  />   
                <beans:bean   class = "com.piaoyi.common.security.DynamicRoleVoter"   />  
            </beans:list >   
        </beans:property >   
    </beans:bean >   
</beans:beans >
UserService.java

public   class  UserService  implements  UserDetailsService{  
    @Autowired   
    private  ISystemUserService userService;  
    @Override   
    public  UserDetails loadUserByUsername(String username)  
            throws  UsernameNotFoundException {  
        // TODO Auto-generated method stub   
        SystemUser user = userService.findById(username);         
        if  (user ==  null )  
            throw   new  UsernameNotFoundException( "The user name "  + username  
                    + " can not be found!" );  
  
        List resultAuths = new  ArrayList();  
               //增加access中配置的权限,实际上这里就是让所有登陆用户都具备该权限,   
               //而真正的资源权限验证留给AccessDecisionManager来决定   
                resultAuths.add(new  GrantedAuthorityImpl( "HODLE" ));  
          
        //验证用户名和密码是否正确,以及是否权限正确   
        return   new  User(username, user.getPassword().toLowerCase(), user.isStatus(),  true ,  
                true ,  true , resultAuths);  
          
          
    }  
} 
DynamicRoleVoter.java

public   class  DynamicRoleVoter   implements   
        AccessDecisionVoter {  
  
    @Autowired   
    private  ISystemUserService userService;  
  
    private  PathMatcher pathMatcher =  new  AntPathMatcher();  
       
    @SuppressWarnings ( "unchecked" )  
    public   boolean  supports(Class clazz) {  
        return   true ;  
    }  
  
       
    public   boolean  supports(ConfigAttribute attribute) {  
        return   true ;  
    }  
  
       
    public   int  vote(Authentication authentication, Object object,  
            java.util.Collection arg2) {  
        int  result = ACCESS_ABSTAIN;  
        if  (!(object  instanceof  FilterInvocation))  
            return  result;  
        FilterInvocation invo = (FilterInvocation) object;  
        String url = invo.getRequestUrl();//当前请求的URL   
        Set authorities = null ;  
        String userId = authentication.getName();  
        //获得当前用户的可访问资源,自定义的查询方法,之后和当前请求资源进行匹配,成功则放行,否则拦截       
        authorities = loadUserAuthorities(userService.findById(userId));  
        Map> urlAuths = authService.getUrlAuthorities();  
        Set keySet = urlAuths.keySet();  
        for  (String key : keySet) {  
            boolean  matched = pathMatcher.match(key, url);  
            if  (!matched)  
                continue ;  
            Set mappedAuths = urlAuths.get(key);  
            if  (contain(authorities, mappedAuths)) {  
                result = ACCESS_GRANTED;  
                break ;  
            }  
        }  
        return  result;  
    }  
      
      
    protected   boolean  contain(Set authorities,  
            Set mappedAuths) {  
        if  (CollectionUtils.isEmpty(mappedAuths)  
                || CollectionUtils.isEmpty(authorities))  
            return   false ;  
        for  (GrantedAuthority item : authorities) {  
            if  (mappedAuths.contains(item.getAuthority()))  
                return   true ;  
        }  
        return   false ;  
    }  
}  


转自:http://blog.sina.com.cn/s/blog_6fda308501016wjy.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值