关于权限控制,一开始感觉比较难,后来先是接触了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. T-SQL 基于关系分割字符串

    今天晚上学习了下 SQL 基于关系的运算,同时也捉摸着写了个例子,虽然我知道性能不是很好,还有待优化.直接上源代码吧,思路表达出来有点困难,直接贴上代码,如果有人不懂得可以MM 我. declare ...

  2. SQL 语句优化—— (一) 操作符优化

    1.IN 操作符 用IN写出来的SQL的优点是比较容易写及清晰易懂,这比较适合现代软件开发的风格.但是用IN的SQL性能总是比较低的,从Oracle执行的步骤来分析用IN的SQL与不用IN的SQL有以 ...

  3. Csharp多态的实现(虚方法)

    1.什么是抽象类 1.1虚方法是用virtual修饰,在子类中用override进行重写 1.2虚方法是一个方法,放在类里面(可以再下面的代码中看到) 1.3虚方法可以 重写,也可以不重写(这个可以再 ...

  4. openwrt看IP流量

    可以利用iptable来实现的,看附件的脚本. 把他放到路由器里面,然后运行. #!/bin/sh echo "Collecting data..." echo "&qu ...

  5. jQuery 迭代器

    在 叶小钗 的博客中看到一段关于遍历的代码 var ajQuery = {}; function dir(elem, dir, until) { var matched = [], truncate ...

  6. jquery的$().each,$.each

    在jquery中,遍历对象和数组,经常会用到$().each和$.each(),两个方法.两个方法是有区别的,从而这两个方法在针对不同的操作上,显示了各自的特点. $().each,对于这个方法,在d ...

  7. hdu 4902 Nice boat 线段树

    题目链接 给n个数, 两种操作, 第一种是将区间内的数变成x, 第二种是将区间内大于x的数变为gcd(x, a[i]). 开三个数组, 一个记录区间最大值, 这样可以判断是否更新这一区间, 一个laz ...

  8. 实验时css层叠样式表不更新的情况

    自定义了CSS的样式,希望在页面中起作用.因为MVC中Views/Shared/_Layout.cshtml是所有视图的公共文件,如下: <!DOCTYPE html> <html& ...

  9. AAU账号分割

    import win.ui; import fsys.dlg; import string.list; /*DSG{{*/ var winform = win.form(text="aard ...

  10. ECC(Error Checking and Correction)校验和纠错

    ECC的全称是 Error Checking and Correction or Error correction Coding,是一种用于差错检测和修正的算法.上一节的BBM中我们提到过,NAND闪 ...