关于权限控制,一开始感觉比较难,后来先是接触了Spring Security 学起来也比较吃力,再是学习了Shiro,感觉简单很多。

总体来说这些框架,主要做了两个事情

Authentication身份认证/登录,验证用户是不是拥有相应的身份;

Authorization授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;

还做了一些事情,我也没有深入,主要就这么。

从以下配置文件可以看出。

<beans:bean id="myFilter" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">

        <beans:property name="authenticationManager" ref="autheticationManager"></beans:property>
        <beans:property name="accessDecisionManager" >
            <beans:bean 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:list>
                </beans:property>
            </beans:bean>
        </beans:property>
        <!-- resourceService在applicationContext*.xml中或注解定义 -->
        <beans:property name="securityMetadataSource" ref="securityMetadataSource" />
    </beans:bean>

这里有一个authenticationManager是做身份认证的,有一个accessDecisionManager是做授权管理的。还有一个是securityMetadataSource这里主要做的从数据库取出资源与角色的关系,为第二个授权做准备,授权又是根据用户的身份找出他的角色,根据角色判断是否有访问资源的权限。

先介绍这个 securityMetadataSource这里需要实现FilterInvocationSecurityMetadataSource接口,大致如下:

/**

     * resourceMa
     * resourceMap 存储的资源为<Url,Collection<ConfigAttribute>>,其中Collection<ConfigAttribute>为资源对应的角色集合,其构造方式为new SecurityConfig("ROLE_" + role.getRoleId().toString())
     * resourceMap 里面存储的内容为<1个URL,对应得角色的集合>
     * 加载所有的资源与角色的关系
     */
    public void init() throws Exception {
        resourceMap = new HashMap<String,Collection<ConfigAttribute>>();
        List<Resource> resources = resourceDao.findAll();
        
        for(Resource item:resources) {
        String url = item.getUrlpath();
            if(url != null) {
                 List<Role> roles = roleDao.getRolesByResourceId(item.getResourceid());
                if(roles !=null && roles.size()>0) {
                    if(resourceMap.containsKey(item.getUrlpath())) {
                        Collection<ConfigAttribute> old = resourceMap.get(item.getUrlpath());
                        old.addAll(listToCollection(roles));
                    } else {
                        resourceMap.put(url, listToCollection(roles));
                    }
                }
            }
        }
    }
    
    /**
     * 将角色转化为ConfigAttribute
     * @param roles
     * @return
     */
    private Collection<ConfigAttribute> listToCollection(Collection<Role> roles) {
        Collection<ConfigAttribute> list = new ArrayList<ConfigAttribute>();
        for(Role role :roles) {
            ConfigAttribute configAttribute = new SecurityConfig("ROLE_"+role.getRoleid().toString());
            //list.add(new SecurityConfig("ROLE_" + role.getRoleid().toString()));
            list.add(configAttribute);
        }
        return list;
        
    }     /**
     * 将资源与权限的对应关系Map转化为Security需要的Collection
     */
    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        Set<ConfigAttribute> allAttributes = new HashSet<ConfigAttribute>();
        for(Map.Entry<String, Collection<ConfigAttribute>>  entry:resourceMap.entrySet()) {
            allAttributes.addAll(entry.getValue());
        }
        return allAttributes;
    }  //返回所请求资源所需要的权限   public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException { String requestUrl = ((FilterInvocation) object).getRequestUrl(); System.out.println("requestUrl is " + requestUrl); if(resourceMap == null) { try { init(); } catch (Exception e) { e.printStackTrace(); } } return resourceMap.get(requestUrl); } 

上面前几个方法是在程序启动的时候执行,最后一个方法是在你要访问某个资源的时候自动调用的最终返回的是 Collection<ConfigAttribute>  权限集合。

accessDecisionManager授权管理,根据上面返回的权限集合,和用户登录存储的用户权限进行对比判断用户是否有访问权限,自己写授权管理的话需要实现AccessDecisionManager 接口,如下:

public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {

        if(configAttributes == null) {
            return;
        }
        //所请求的资源拥有的权限(一个资源对多个权限)
        Iterator<ConfigAttribute> iterator = configAttributes.iterator();
        while(iterator.hasNext()) {
            ConfigAttribute configAttribute = iterator.next();
            //访问所请求资源所需要的权限
            String needPermission = configAttribute.getAttribute();
            System.out.println("needPermission is " + needPermission);
            //用户所拥有的权限authentication
            for(GrantedAuthority ga : authentication.getAuthorities()) {
                if(needPermission.equals(ga.getAuthority())) {
                    return;
                }
            }
        }
        //没有权限让我们去捕捉
        throw new AccessDeniedException(" 没有权限访问!");

}

authenticationManager身份认证,主要包含登陆这些,框架一般会给我们提供form表单提交的处理接口,我们需要实现接口和配置一些相关配置。

<http auto-config="true" access-denied-page="/accessDenied.jsp" use-expressions="true">

        <form-login login-page="/index.jsp" login-processing-url="/j_spring_security_check"
        always-use-default-target="true" authentication-failure-url="/index.jsp?login_error=true"
        default-target-url="/frame.jsp"
        />
                
        <logout logout-success-url="/index.jsp"/>
        <intercept-url pattern="/style/**" filters="none" />
        <intercept-url pattern="/js/**" filters="none" />
         <intercept-url pattern="/index.jsp" filters="none" />
        <intercept-url pattern="/login.action" filters="none"/>
        <intercept-url pattern="/frame.jsp" access="isAuthenticated()"/>
        <anonymous />
        <session-management invalid-session-url="/accessDenied.jsp">
            <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
        </session-management>
        <!-- 将自己的过滤器加入到过滤器链中, 放在FILTER_SECURITY_INTERCEPTOR之前-->
        <custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR"/>
    </http>
    
    <authentication-manager alias="autheticationManager">
        <!-- 使用自定义UserDetailsService -->
        <authentication-provider user-service-ref="userService"/>

</authentication-manager>

以上是Spring Security的配置,还需要在userService 登录验证里面实现UserDetailsService 接口。Shiro实现方式如下 :

Subject currentUser = SecurityUtils.getSubject();

        System.out.println(EncryptUtils.encryptMD5(user.getPassword()));
        UsernamePasswordToken token = new UsernamePasswordToken(
                user.getUsercode(), EncryptUtils.encryptMD5(user.getPassword()));
        token.setRememberMe(true);
        try {
            currentUser.login(token);
        } catch (AuthenticationException e) {
            modelView.addObject("message", "login errors");
            modelView.setViewName("/login");
            e.printStackTrace();
            

}

accessDecisionManager

权限控制框架Spring Security 和Shiro 的总结的更多相关文章

  1. 了解权限控制框架shiro 之实际应用.

    Apache Shiro 1.权限控制分为 a.粗粒度 URL 级别权限控制     b.细粒度方法级别权限控制 2.使用shiro进行权限控制主要有四种主要方式 : a. 在程序中 通过 Subje ...

  2. 项目一:第十二天 1、常见权限控制方式 2、基于shiro提供url拦截方式验证权限 3、在realm中授权 5、总结验证权限方式(四种) 6、用户注销7、基于treegrid实现菜单展示

    1 课程计划 1. 常见权限控制方式 2. 基于shiro提供url拦截方式验证权限 3. 在realm中授权 4. 基于shiro提供注解方式验证权限 5. 总结验证权限方式(四种) 6. 用户注销 ...

  3. Spring Security和Shiro的比较和使用

    https://blog.csdn.net/it_java_shuai/article/details/78054951 Spring Security和Shiro的比较和使用 2017年09月21日 ...

  4. Spring Boot + Spring Cloud 实现权限管理系统 (Spring Security 版本 )

    技术背景 到目前为止,我们使用的权限认证框架是 Shiro,虽然 Shiro 也足够好用并且简单,但对于 Spring 官方主推的安全框架 Spring Security,用户群也是甚大的,所以我们这 ...

  5. Flex-Security权限控制框架

    转自:http://code.google.com/p/flex-security/ flex UI组件权限控制框架 一.快速开始 1) 下载并添加flex_security.swf在你的flex l ...

  6. WPF权限控制框架——【4】抛砖引玉

    写第一篇"权限控制框架"系列博客是在2021-01-29,在这不到一个月的时间里,收集自己零碎的时间,竟然写出了一个"麻雀虽小,五脏俱全"的权限控制框架:对于一 ...

  7. 权限控制框架Shiro简单介绍及配置实例

    Shiro是什么 http://shiro.apache.org/ Apache Shiro是一个非常易用的Java安全框架,它能提供验证.授权.加密和Session控制.Shiro非常轻量级,而且A ...

  8. shiro权限控制(一):shiro介绍以及整合SSM框架

    shiro安全框架是目前为止作为登录注册最常用的框架,因为它十分的强大简单,提供了认证.授权.加密和会话管理等功能 . shiro能做什么? 认证:验证用户的身份 授权:对用户执行访问控制:判断用户是 ...

  9. 第十九章 动态URL权限控制——《跟我学Shiro》

    目录贴:跟我学Shiro目录贴 用过Spring Security的朋友应该比较熟悉对URL进行全局的权限控制,即访问URL时进行权限匹配:如果没有权限直接跳到相应的错误页面.Shiro也支持类似的机 ...

随机推荐

  1. Oracle集合操作函数:union、intersect、minus

    [转]Oracle集合操作函数:union.intersect.minus 集合操作符专门用于合并多条select 语句的结果,包括:UNION, UNION ALL, INTERSECT, MINU ...

  2. SQL中存储过程和自定义函数的区别(转载)

    存储过程:     存储过程可以使得对数据库的管理.以及显示关于数据库及其用户信息的工作容易得多.存储过程是 SQL 语句和可选控制流语句的预编译集合,以一个名称存储并作为一个单元处理.存储过程存储在 ...

  3. STL模板_概念

    模板和STL一.模板的背景知识1.针对不同的类型定义不同函数版本.2.借助参数宏摆脱类型的限制,同时也因为失去的类型检查而引 入风险.3.借助于编译预处理器根据函数宏框架,扩展为针对不同类型的 具体函 ...

  4. SGU 149. Computer Network( 树形dp )

    题目大意:给N个点,求每个点的与其他点距离最大值 很经典的树形dp...很久前就想写来着...看了陈老师的code才会的...mx[x][0], mx[x][1]分别表示x点子树里最长的2个距离, d ...

  5. JavaScript之转义字符

    <html lang="en"> <head>   <meta charset="UTF-8">   <meta na ...

  6. page cache和buffer cache

    因为要优化I/O性能,所以要理解一下这两个概念,这两个cache着实让我迷糊了好久,通过查资料大概明白了两者的区别,试着说下. page cache:文件系统层级的缓存,从磁盘里读取的内容是存储到这里 ...

  7. C语言2

    函数是C语言的基本单位,类是java,c#,c++的基本单位 int abs(int x); double fabs(double x);   按变量的存储方式:静态变量.自动变量.寄存器变量 指针就 ...

  8. switch使用方法之一周食谱例

    /* Name:switch使用方法之一周食谱例 Copyright: By.不懂网络 Author: Yangbin Date:2014年2月17日 03:52:53 Description: */ ...

  9. android小知识之多个listview在同一界面只有item高亮

    我的工程里面一个activity有两个有圆角的listview,就是 自定义的 CornerListView继承ListView,  然后  我想圆角的listview A点击之后一个item会高亮  ...

  10. ios post空文件流导致400错误