美文网首页
springboot整合shiro---认证及授权

springboot整合shiro---认证及授权

作者: 毛于晏 | 来源:发表于2018-11-17 17:36 被阅读45次

    最近来新项目, 后台管理, 说道管理, 肯定是需要权限; 又把之前看的shiro拿出来用, 因为之前用的springMVC, 懂的也是半吊子, 这次用springboot也费老劲了, 但是还是让我把它的基本用法搞懂了, 下面分享下;

    1.上jar包

    <!--shiro-->
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring</artifactId>
                <version>1.4.0</version>
            </dependency>
    

    2.shiro配置类

    package cn.cooplan.data_statistical.config;
    
    import org.apache.shiro.spring.LifecycleBeanPostProcessor;
    import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
    import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
    import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
    import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.DependsOn;
    
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    /**
     * @Author MaoLG
     * @Date 2018/11/17  11:24
     */
    @Configuration
    public class ShiroConfig {
    
    
        /**
         * LifecycleBeanPostProcessor,这是个DestructionAwareBeanPostProcessor的子类,
         * 负责org.apache.shiro.util.Initializable类型bean的生命周期的,初始化和销毁。
         * 主要是AuthorizingRealm类的子类,以及EhCacheManager类。
         */
        @Bean(name = "lifecycleBeanPostProcessor")
        public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
            return new LifecycleBeanPostProcessor();
        }
    
        /**
         * ShiroRealm,这是个自定义的认证类,继承自AuthorizingRealm,
         * 负责用户的认证和权限的处理,可以参考JdbcRealm的实现。
         * 这个类是我自己定义的, 因为要根据自己实际需求来进行权限校验
         */
        @Bean(name = "shiroRealm")
        @DependsOn("lifecycleBeanPostProcessor")
        public ShiroRealm shiroRealm() {
            ShiroRealm realm = new ShiroRealm();
            return realm;
        }
    
        /**
         * SecurityManager,权限管理,这个类组合了登陆,登出,权限,session的处理,是个比较重要的类。
         *
         * @return
         */
        @Bean(name = "securityManager")
        public DefaultWebSecurityManager securityManager() {
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            securityManager.setRealm(shiroRealm());
            return securityManager;
        }
    
        /**
         * ShiroFilterFactoryBean,是个factorybean,为了生成ShiroFilter。
         * 它主要保持了三项数据,securityManager,filters,filterChainDefinitionManager。
         * 该类类似springmvc配置的访问权限设置
         */
        @Bean(name = "shiroFilter")
        public ShiroFilterFactoryBean shiroFilterFactoryBean() {
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            shiroFilterFactoryBean.setSecurityManager(securityManager());
    
            //url权限配置, url为controller设置的可访问的路径 ps:url可以使用*(通配符设置)
            Map<String, String> filterChainDefinitionManager = new LinkedHashMap<String, String>();
            //可以匿名访问的权限 anon:不登录也可访问
            filterChainDefinitionManager.put("/user/login", "anon");
            //必须登录的权限 authc:必须登录才能访问的权限
            filterChainDefinitionManager.put("/user/test", "authc");
            //退出登录 logout:退出登录, shiro帮我们实现, 该路径方法可不编写任何逻辑,可清楚shiro记录的认证
            // 每次去认证的时候, 如果不调用该接口, 不会访问数据库去认证 会直接从shiro的缓存中拿取认证信息, 在适当情况调用该接口
            filterChainDefinitionManager.put("/user/logout", "logout");
    
            //权限访问, 不能动态获取, 代码写死, 没找到动态获取方法
            filterChainDefinitionManager.put("/user/test", "perms[测试]");
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionManager);
    
            return shiroFilterFactoryBean;
        }
    
        /**
         * DefaultAdvisorAutoProxyCreator,Spring的一个bean,由Advisor决定对哪些类的方法进行AOP代理。
         */
        @Bean
        @ConditionalOnMissingBean
        public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
            DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
            defaultAAP.setProxyTargetClass(true);
            return defaultAAP;
        }
    
        /**
         * AuthorizationAttributeSourceAdvisor,shiro里实现的Advisor类,
         * 内部使用AopAllianceAnnotationsAuthorizingMethodInterceptor来拦截用以下注解的方法。
         */
        @Bean
        public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
            AuthorizationAttributeSourceAdvisor aASA = new AuthorizationAttributeSourceAdvisor();
            aASA.setSecurityManager(securityManager());
            return aASA;
        }
    }
    

    3.自定义realm

    package cn.cooplan.data_statistical.config;
    
    import cn.cooplan.data_statistical.dao.PermissionDao;
    import cn.cooplan.data_statistical.dao.UserDao;
    import cn.cooplan.data_statistical.pojo.Permission;
    import cn.cooplan.data_statistical.pojo.User;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    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;
    import org.springframework.beans.factory.annotation.Autowired;
    
    import java.util.List;
    
    /**
     * 自定义realm
     *
     * @Author MaoLG
     * @Date 2018/11/17  13:03
     */
    public class ShiroRealm extends AuthorizingRealm {
        //读取用户权限,我这里没有角色表, 具体根据自己实际需求编写
        @Autowired
        private PermissionDao permissionDao;
    
        /**
         * 授权
         * 实现授权具体业务
         * @param principalCollection
         * @return
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            //获得登录时提供的重要凭证, 这里获得的是登录账号
            String username = (String) principalCollection.getPrimaryPrincipal();
            //查询到该账号下所有的权限
            List<Permission> permissions = permissionDao.selectUserOwnPermission(username);
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
          //把用处所有权限加在SimpleAuthorizationInfo 对象中, shiro自己来读取对比权限
            for (Permission permission: permissions){
                info.addStringPermission(permission.getName());
            }
          //如果有角色的需要, 调用info.addRole("角色"); 同权限一个道理
            return info;
        }
    
        /**
         * 认证
         *
         * @param authenticationToken
         * @return
         * @throws AuthenticationException
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) 
    throws AuthenticationException {
            SimpleAuthenticationInfo info = null;
            try {
                //强转UsernamePasswordToken 类型
                UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
                //获得登录账号
                String username = token.getUsername();
    
                char[] pwd = token.getPassword();
                //获得登密码
                String password = String.valueOf(pwd);
                //shiro默认配置回去找t_user表 来查询 , 也可根据自己实际业务编写
                info = new SimpleAuthenticationInfo(username, password, getName());
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            return info;
        }
    }
    

    这里没有使用rememberMe(记住我--实现自动登录), 有需要的大家自行先百度, 后期如果使用到会更新上去

    相关文章

      网友评论

          本文标题:springboot整合shiro---认证及授权

          本文链接:https://www.haomeiwen.com/subject/lhlifqtx.html