关于权限控制,一开始感觉比较难,后来先是接触了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. mysql的触发器

    删除触发器 drop TRIGGER 触发器名字; 查找库里面的所有触发器 SELECT * FROM information_schema.`TRIGGERS`;show triggers 触发器语 ...

  2. Asp.Net 禁用cookie后使用session

    原文地址:http://www.c-sharpcorner.com/UploadFile/deepak.sharma00/using-cookie-less-session-in-Asp-Net/ H ...

  3. spoj 1557 GSS3 - Can you answer these queries III 线段树

    题目链接 给出n个数, 2种操作, 一种是将第x个数改为y, 第二种是询问区间[x,y]内的最大连续子区间. 开4个数组, 一个是区间和, 一个是区间最大值, 一个是后缀的最大值, 一个是前缀的最大值 ...

  4. 经典灰鸽子lcx

    方法1路由配置 在路由器配置 进入虚拟服务器 填入ip 端口 就可以了方法2内网域名解析想以前的花生客 科迈都有这项免费业务但现在基本不提供了如果那个网站还有内网解析的功能 大家一定要发上来哦方法3p ...

  5. Netty那点事: 概述, Netty中的buffer, Channel与Pipeline

    Netty那点事(一)概述 Netty和Mina是Java世界非常知名的通讯框架.它们都出自同一个作者,Mina诞生略早,属于Apache基金会,而Netty开始在Jboss名下,后来出来自立门户ne ...

  6. jquery submit()不能提交表单的解决方法

    <form id="form" method="get"> <input type="text" name="q ...

  7. 《windows程序设计》学习_3.3:利用xp扫雷资源

    #include<windows.h> #include "resource.h" LRESULT CALLBACK WndProc (HWND, UINT, WPAR ...

  8. InitParam与ContextParm的异同

    web.xml里面可以定义两种参数:(1)application范围内的参数,存放在servletcontext中,在web.xml中配置如下: xml 代码 <context-param> ...

  9. proguard混淆jar文件

    Proguard是个优秀的java混淆工具,使用示例如下,一个java工程对外接口代码如下(无需混淆) package com.ciaos.open; import com.ciaos.inner.I ...

  10. Delphi Excel FastReport

    unit Unit1; interface uses Printers,Windows, Messages, SysUtils, Variants, Classes, Graphics, Contro ...