shiro相关

shiro相关

  1. 权限管理:一句话概述就是赋予用户不同角色从而拥有不同的功能.
  2. Apache Shiro
    1. Shiro 比 Spring Security更容易上手使用和理解,Shiro 可以不跟任何的框架或者容器绑定,可独立运
      行,而Spring Security 则必须要有Spring环境, Shiro 可能没有 Spring Security 做的功能强大,但是
      在实际工作时可能并不需要那么复杂的东西,所以使用小而简单的 Shiro 就足够了
    2. Shiro 可以帮助我们完成:认证、授权、加密、会话管理、与 Web 集成、缓存等.
    3. Subject(用户): 访问系统的用户,主体可以是用户、程序等,进行认证的都称为主体;Subject 一词是一个专业术语,其基本意思是“当前的操作用户”。在程序任意位置可使用:Subject currentUser = SecurityUtils.getSubject() 获取到subject主体对象,类似 Employee user = UserContext.getUser()
    4. SecurityManager(安全管理器):它是 shiro 功能实现的核心,负责与后边介绍的其他组件(认证器/授权器/缓存控制器)进行交互,实现 subject 委托的各种功能。有点类似于SpringMVC 中DispatcherServlet 前端控制器,负责进行分发调度。
    5. Realms(数据源): Realm 充当了 Shiro 与应用安全数据间的“桥梁”或者“连接器”。;可以把Realm 看成 DataSource,即安全数据源。执行认证(登录)和授权(访问控制)时,Shiro 会从应用配置的 Realm 中查找相关的比对数据。以确认用户是否合法,操作是否合理。
    6. Authenticator(认证器): 用于认证,从 Realm 数据源取得数据之后进行执行认证流程处理。
    7. Authorizer(授权器):用户访问控制授权,决定用户是否拥有执行指定操作的权限。
    8. SessionManager (会话管理器):Shiro 与生俱来就支持会话管理,这在安全类框架中都是独一无二的功能。即便不存在 web 容器环境,shiro 都可以使用自己的会话管理机制,提供相同的会话 API。
    9. CacheManager (缓存管理器):用于缓存认证授权信息等。
    10. Cryptography(加密组件): Shiro 提供了一个用于加密解密的工具包。
  3. 架包导入
        <dependency>
            <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.3</version>
        </dependency> 
        <dependency> 
            <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.5.2</version> 
        </dependency> 
        <dependency> 
            <groupId>junit</groupId> 
            <artifactId>junit</artifactId> 
            <version>4.13.2</version> 
        </dependency> 
        <dependency>
            <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.22</version> <scope>provided</scope>
        </dependency>
    
  4. 基本案例
    @Test public void testLogin(){ 
            //创建Shiro的安全管理器,是shiro的核心 
            DefaultSecurityManager securityManager = new DefaultSecurityManager(); 
            //加载shiro.ini配置,得到配置中的用户信息(账号+密码)  IniRealm iniRealm = new IniRealm("classpath:shiro-authc.ini");
            securityManager.setRealm(iniRealm);
             //把安全管理器注入到当前的环境中 
            SecurityUtils.setSecurityManager(securityManager); 
            //无论有无登录都可以获取到subject主体对象,但是判断登录状态需要利用里面的属性来判断 
            Subject subject = SecurityUtils.getSubject(); System.out.println("认证状态:"+subject.isAuthenticated()); 
            //创建令牌(携带登录用户的账号和密码) 
            UsernamePasswordToken token = new UsernamePasswordToken("dafei","666"); 
            //执行登录操作(将用户的和 ini 配置中的账号密码做匹配) 
            subject.login(token); 
            System.out.println("认证状态:"+subject.isAuthenticated());
           //登出 //subject.logout(); 
           //System.out.println("认证状态:"+subject.isAuthenticated()); 
        }
    
  5. 自定义realm
    public class EmployeeRealm extends AuthorizingRealm {
         @Autowired
        private IEmployeeService employeeService;
        @Autowired
        private IRoleService roleService;
        @Override
        protected AuthenticationInfo 
        doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
    
        //根据名字查询对应的employee对象
        String username = (String)authenticationToken.getPrincipal();
        Employee employee = employeeService.selectByUsername(username);
        if (employee != null){
            return new SimpleAuthenticationInfo(employee, employee.getPassword(), this.getName());
        }
        return null;
    }
    
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
      Employee employee = (Employee) principalCollection.getPrimaryPrincipal();
        System.out.println("employee = " + employee);
        // Subject subject = SecurityUtils.getSubject();
        // Employee employee = (Employee)subject.getPrincipal();
        //超管拥有所有的权限
        if (employee.isAdmin()){
            // info.addRole("admin");
            List<Role> roles =  roleService.listAll();
            List<String> roleSns = new ArrayList<>();
            for (Role role : roles) {
                roleSns.add(role.getSn());
            }
            info.addRoles(roleSns);
            //*:*表示所有权限,不做控制,如果是employee:*就表示可以访问employee路径下的所有资源
            info.addStringPermission("*:*");
    
        }else {
            //普通员工就只拥有对应角色的权限
            //将所有的角色加入info
            List<String> roleSns =  employeeService.selectSnByEmpId(employee.getId());
            info.addRoles(roleSns);
    
            //查询所有的权限加入info
            List<String> permissions = employeeService.selectPermissionsByEmpId(employee.getId());
            info.addStringPermissions(permissions);
        }
    
        return info;
    }
    
    public void clearCache() {
        System.out.println("清除缓存数据");
        Subject subject=SecurityUtils.getSubject();
        // 调用子类去清理缓存
        super.clearCache(subject.getPrincipals());
    }
    
    }
    
  6. 如何在项目中集成shiro呢?
    1. 导入shiro相关的jar包
    2. 在web.xml中配置一个代理过滤器(org.springframework.web.filter.DelegatingFilterProxy)取名为shiroFilter,然后新建一个shiroFilter.xml的配置文件,将该配置文件导入到mvc.xml中,因为shiroFilter是不依赖spring容器的,而且其配置比较复杂(因此单独建立一个shiroFilter.xml),所以我们为了让spring帮我们管理,并且利于管理就使用了代理过滤器作为一个桥梁,当有请求访问时,就会被代理filter拦截,然后去spring容器中找到同名的(取名为shiroFilter)bean对象,所以在shiroFilter.xml中我们配置的真正的shiro的过滤器,名字一定要和代理过滤器中的名字一样,一般都为shiroFilter
    3. 在需要做权限控制的地方贴上注解@RequiresPermissions,注意了:这是shiro的注解,不是我们自定义的
    4. 自定好realm,在protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection)方法中(重载的方法),将该对象拥有的所有角色和权限都加入进去,这里要额外注意下超管的处理,因为超管拥有所有的权限,所以要把所有的权限都给它
    5. 注意点:SecurityUtils.getSubject();这个方法在项目任何地方都可以使用,所以如果我们想通过编程式的方式来进行权限控制的话,可以直接在我们想要控制的资源那里通过if(subject.hasRole("hr"))这种形式来判断
    6. 当一个方法上贴了权限注解,就表示当前登录的用户必须拥有该权限才可以访问,如果还贴了@RequiresRoles
  7. @RequiresPermissions注解的灵活使用,这玩意儿不像我们自己定义的注解可以带上名字什么的,它就一个value属性,所以我们只能传入权限表达式,但是存在数据库还是展示在后台页面都是达不到需求的,因为@RequiresPermissions注解可以接受一个数组,所以我们默认传一个数组进去,第一个元素为表达式,第二个为name(给表达式取的名字),这样就可以达到我们的需求了,但同时必须注意要设置@RequiresPermissions注解的属性logical = Logical.OR,这个表示数组里面的元素有一个符合条件就行
  8. 如果我们的前端页面选择的是freemarker(shiro默认支持的是jsp,freemarker是不支持shiro的),那么我们就要自定义FreeMarkerConfigurer了,将shiro标签注册进freemarker中,示例如下
    public class ShiroFreeMarkerConfig extends FreeMarkerConfigurer {
        @Override
        public void afterPropertiesSet() throws IOException, TemplateException {
            //继承之前的属性配置
            super.afterPropertiesSet();
            Configuration configuration = this.getConfiguration();
            //注册shiro标签,在freemarker中使用的时候都是@shiro这种类型的
            configuration.setSharedVariable("shiro",new ShiroTags());
        }
    }
    

并且要在mvc.xml的配置中(freemarker)改成我们自定义的<bean class="cn.wolfcode.crm.util.ShiroFreeMarkerConfig">
- 然后就可以使用一系列标签了

  1. <@shiro.authenticated> 已认证通过的用户/@shiro.authenticated
  2. <@shiro.notAuthenticated>认证未通过的用户/@shiro.notAuthenticated
  3. <@shiro.principal property="name" />输出当前登录的用户名(这里的name属性是对应的登录用户对象里面的属性,不一定非得叫name)
  4. <@shiro.hasRole name="admin">是否拥有该角色/@shiro.hasRole
  5. <@shiro.hasPermission name="department:delete">是否拥有该权限/@shiro.hasPermission
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容