• SpringBoot与Shiro整合权限管理实战


    SpringBoot与Shiro整合权限管理实战

    作者 : Stanley 罗昊

    转载请注明出处和署名,谢谢!

    *观看本文章需要有一定SpringBoot整合经验*

    Shiro框架简介

    Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码学和会话管理。使用Shiro的易于理解的API,可以快速、轻松地获得任何应用程序,

    从最小的移动应用程序到最大的网络和企业应用程序。

    分析Shiro的核心API

    其实,Shiro的核心类有三个,分别是:

    1.Subject:这个类呢,我们称之当前用户的主体,这个用户的主体包含了登陆、注销等等的一些方法,还有一些判断授权的一些方法;

    2.SecurityManager:这个名称翻译过来就是,安全管理器的意思;

    3.Realm:这个Realm呢其实我们Shiro去链接数据库的一个桥梁,因为,我们的程序需要去操作数据库去获取一些用户的信息,这些操作都需要Realm去完成;

    这个三个API呢,都存在一些关系,比如.SecurityManager是需要去关联我们的Realm,Subject是需要把操作交给我们的SecurityManager,总结下来就是,Subject是需要去管理我们的SecurityManager,而SecurityManager去关联我们的Realm;

    以上就是对Shiro的核心API进行的一些分析;

    分析完之后,我们接下来就直接用SpringBoot与Shiro的整合,我们来看下它整合的关键步骤

    SpringBoot整合Shiro

    那么这个整合首先第一步需要导入Shiro的依赖;

    【因为我用的是Gradle,所以仅展示Gradle用法】

    1.修改.gradle文件,添加以下依赖

    //Thymeleaf模板引擎,因为我用模板引擎所以我添加了此依赖
            compile group: 'org.thymeleaf', name: 'thymeleaf', version: '3.0.11.RELEASE'
            //Shiro
            compile group: 'org.apache.shiro', name: 'shiro-web', version: '1.4.0'
            compile group: 'org.apache.shiro', name: 'shiro-core', version: '1.4.0'
            // https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring
            compile group: 'org.apache.shiro', name: 'shiro-spring', version: '1.4.0'

    2.编写Shiro的配置类

    配置类需要三样API,分别是:

     /**
         * 创建ShiroFilterFactoryBean
         * shiro过滤bean
         */
    
    /**
         * 创建DefaultWebSecurityManager
         */
    
        /**
         * 创建Realm
         */

    如图:

    3.自定义Realm类

    因为我们需要在配置类中创建出Realm对象,所以我们需要建一个名为Realm的类:

    创建后,需要继承一个方法,这个方法是Shiro提供的:

    /**
     * 自定义Realm
     */
    public class UserRealm extends AuthorizingRealm {
        //执行授权逻辑
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    
            return null;
        }
    
        //执行认证逻辑
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
          
            return null;
    
        }

    4.在配置类中new出Realm

    Shiro配置配置类

    package com.lh.shiroStudy.shiro;
    
    
    import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
    import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    
    /**
     * Shiro配置类
     */
    //@Configuration,声明本类是一个配置类
    @Configuration
    public class ShiroConfig {
    
        /**
         * 创建ShiroFilterFactoryBean
         * shiro过滤bean
         */
        @Bean
        public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            //设置安全管理器
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            //添加Shiro过滤器
            /**
             * Shiro内置过滤器,可以实现权限相关的拦截器
             *  常用的过滤器:
             *      anon: 无需认证(登录)可以访问
             *      authc: 必须认证才可以访问
             *      user: 如果使用rememberMe功能可以直接访问
             *      perms: 该资源必须得到资源权限才可以访问
             *      role: 该资源必须得到角色权限才可以访问
             */
    
            Map<String,String>filterMap = new LinkedHashMap<String, String>();
            //左边编写拦截路径
            filterMap.put("/add","authc");
            filterMap.put("/update","authc");
            filterMap.put("/testThymeleaf","authc");
            //授权过滤器
            //注意:当前授权拦截后,shiro会自动跳转未授权页面
            filterMap.put("/add","perms[user:add]");
    
            //修改跳转的登陆页面
            shiroFilterFactoryBean.setLoginUrl("/toLogin");
    
            //转跳至未授权页面【友好提示】
            shiroFilterFactoryBean.setUnauthorizedUrl("/aaaaaa");//懒省事所以没有aaaa这个页面,如果需要,请在Contoller中添加
    
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
            return shiroFilterFactoryBean;
        }
    
    
        /**
         * 创建DefaultWebSecurityManager
         */
        @Bean(name = "securityManager")
        public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("UserRealm") UserRealm userRealm){
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            securityManager.setRealm(userRealm);
            return securityManager;
        }
    
    
    
        /**
         * 创建Realm
         */
        @Bean(name = "UserRealm")
        public UserRealm getRealm(){
            return new UserRealm();
        }
    
    }

    Realm类

    package com.lh.shiroStudy.shiro;
    
    import org.apache.shiro.authc.*;
    import org.apache.shiro.authz.AuthorizationInfo;
    import org.apache.shiro.authz.SimpleAuthorizationInfo;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.subject.PrincipalCollection;
    
    
    /**
     * 自定义Realm
     */
    public class UserRealm extends AuthorizingRealm {
        //执行授权逻辑
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    
            //给资源进行授权
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
    
            //添加资源的授权字符串
            //info.addStringPermission("user:add");
    
            //到数据库查询当前登陆用户的授权字符串
            /**
             * <!-演示状态-!>
             *     获取当前用户
             *     Subject subject = SecurityUtils.getSubject();
             *     User user = (User)subject.getPrincipal();
             *     User dbUser = userService.findById(id)
             *     info.addStringPermission(dbUser.getPerms());
             * </!-演示状态-!>
             */
            System.out.println("执行授权逻辑");
            return null;
        }
    
        //执行认证逻辑
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
            System.out.println("执行认证逻辑");
            //假设数据库账号与密码是如下
            String username = "admin";
            String password = "123456";
            /**
             * 编写Shiro判断逻辑,比对用户名和密码
             */
            //1.判断用户名
            UsernamePasswordToken token =(UsernamePasswordToken)arg0;
    
            //User user = userService.findByName(token.getUsername());
    
            if (user == null){
                //用户名不存在
                return null;//如果返回null,Shiro底层会抛出UnknowAccountException
            }
            //2.判断密码
            /**
             * 有三个参数
             * 1.需要返回给login
             * 2.是数据库的密码,将数据库密码返回,Shiro会自动判断
             * 3.是Shiro的名字
             */
            return new SimpleAuthenticationInfo(user,password,"");
    
        }
    }
  • 相关阅读:
    服务方式加载卸载NT驱动函数集
    《Windows核心编程》学习笔记(12)– 虚拟内存
    《Windows核心编程》学习笔记(14)– 堆
    数据库连接错误:提示TCP端口1433,sql server 2008 Connection refused:connect
    Windows驱动开发技术详解笔记
    Struts2文件上传的大小限制问题
    pragma comment的使用 pragma预处理指令详解
    解决FastCGI Error Error Number: 2147467259 (0x80004005). 和 Error Number: 1073741819 (0xc0000005).
    PHP中的日期处理
    mysql远程连接10061错误
  • 原文地址:https://www.cnblogs.com/StanleyBlogs/p/11407350.html
Copyright © 2020-2023  润新知