美文网首页shirosso
shiro(15)-springboot2.x整合shiro(无

shiro(15)-springboot2.x整合shiro(无

作者: 小胖学编程 | 来源:发表于2019-10-12 17:28 被阅读0次

    shiro安全控制目录

    前后端分离的架构中,采用的是Token的无状态认证模式。

    token认证架构图.png

    1. Maven依赖

            <!--shiro的核心依赖包-->
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-core</artifactId>
                <version>1.2.3</version>
            </dependency>
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-web</artifactId>
                <version>1.2.3</version>
            </dependency>
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring</artifactId>
                <version>1.2.3</version>
            </dependency>
    

    2. 配置

    在普通的Spring项目中,Filter是由Servlet管理,需要我们在web.xml配置。但是在SpringBoot2.x中,所有的Servlet或者Filter 的Beans都会被servlet容器自动注册。

    (1)shiro要配置一个servlet Filter,过滤所有的请求。

    org.apache.shiro.spring.web.ShiroFilterFactoryBean是一个BeanFactory,实际返回bean为getObject()返回值,也就是org.apache.shiro.web.servlet.AbstractShiroFilter对象(Servlet Filter的子类)。

        @Bean(name="shiroFilterFactoryBean")
        public ShiroFilterFactoryBean shirFilter(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            shiroFilterFactoryBean.setSecurityManager(securityManager);     //设置安全管理器
            shiroFilterFactoryBean.setLoginUrl("/login");//     如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
            shiroFilterFactoryBean.setSuccessUrl("/index"); //  登录成功后要跳转的链接
            shiroFilterFactoryBean.setUnauthorizedUrl("/noAuth");//未授权界面;
            Map<String, String> filterMap = new HashMap<String, String>();
                filterMap.put("/css/**","anon");
                filterMap.put("/layui/**","anon");
                filterMap.put("/img/**","anon");
                filterMap.put("/js/**","anon");
                filterMap.put("/html/**","anon");
                filterMap.put("/login/index","authc");
                filterMap.put("/login/login","anon");
                filterMap.put("/logout","logout");//配置退出 过滤器,其中的具体的退出代码Shiro已经实现
                filterMap.put("/**","authc");//过滤链定义,从上向下顺序执行,一般将/**放在最为下边
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
            return shiroFilterFactoryBean ; 
            }
    

    (2)shiro需要配置SecurityManager,协调管理所有组件。

    shiro通过servlet Filter过滤所有的请求,但是如何去协调管理或自定义配置诸如(Realm、SessionManager、rememberMananger、CacheManager)组件,需要由SecurityMananger这位shiro大管家操心。

    1. SubjectContext在创建的时候,需要关闭session的创建,这个由DefaultWebSubjectFactorycreateSubject进行管理。
    2. 禁用Session作为存储的实现,这个主要由subjectDAOsessionStorageEvaluator进行管理。
    3. 禁用session调度器,主要用sessionManager进行管理。
        @Bean
        public SecurityManager securityManager(DefaultWebSubjectFactory jwtDefaultSubjectFactory, DefaultWebSessionManager sessionManager, DefaultSubjectDAO defaultSubjectDAO) {
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            //配置Realm
            securityManager.setRealm(userAuthorizingRealm);
            //配置SubjectFactory,禁止创建Session
            securityManager.setSubjectFactory(jwtDefaultSubjectFactory);
            //配置sessionManager
            securityManager.setSessionManager(sessionManager);
            //配置SubjectDAO,subject禁止存储到session
            securityManager.setSubjectDAO(defaultSubjectDAO);
            return securityManager;
        }
    
        @Bean
        public DefaultWebSessionManager sessionManager() {
            DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
            sessionManager.setSessionIdCookieEnabled(false);
            sessionManager.setSessionValidationSchedulerEnabled(false);
            return sessionManager;
        }
    
        @Bean
        public DefaultSubjectDAO defaultSubjectDAO() {
            return new DefaultSubjectDAO() {
                @Override
                protected boolean isSessionStorageEnabled(Subject subject) {
                    return false;
                }
            };
        }
    
        @Bean
        public DefaultWebSubjectFactory jwtDefaultSubjectFactory() {
            return new JwtDefaultSubjectFactory() {
                @Override
                public Subject createSubject(SubjectContext context) {
                    // 不创建session
                    context.setSessionCreationEnabled(false);
                    Subject subject = super.createSubject(context);
                    return subject;
                }
            };
        }
    
        @Bean
        public UserAuthorizingRealm userAuthorizingRealm(){
            UserAuthorizingRealm userAuthorizingRealm = new UserAuthorizingRealm();
            //暂时不使用缓存
            userAuthorizingRealm.setAuthorizationCachingEnabled(false);
            return userAuthorizingRealm;
        }
    

    (3)自定义shiroFilter

    在shiro中可以自定义过滤器链,对url进行精细化的控制。shiro Filter也是Servlet Filter的子类。使用@Bean将Shiro Filter Bean加入到容器时,Filter会自动注册到Servlet Filter Chain中,并且拦截路径默认为/。需要取消Filter的自动注册,手动的加入到Shiro Filter Chain中。

        //自定义权限过滤器
        @Bean
        public FilterRegistrationBean myPermissionFilterBean(MyPermissionFilter myPermissionFilter) {
            FilterRegistrationBean registration = new FilterRegistrationBean(myPermissionFilter);
            //取消自动注册
            registration.setEnabled(false);
            return registration;
        }
    

    shiro(7)-shiroFilter(url上的权限控制)

    也可以动态的配置过滤器链。

        @Bean("shiroFilterBean")
        public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            shiroFilterFactoryBean.setSecurityManager(securityManager);
    
            shiroFilterFactoryBean.setFilterChainDefinitionMap(section);
            Map<String, Filter> filterMap = new HashMap<String, Filter>() {{
                put("authcFilter", myAuthcFilter);
                put("permissionFilter", myPermissionFilter);
            }};
            shiroFilterFactoryBean.setFilters(filterMap);
            return shiroFilterFactoryBean;
        }
    
        @Bean
        public ChainDefinitionSectionMetaSource section(){
            //FactoryBean<Section>的子类,动态的拼装org.apache.shiro.config.Ini.Section类型。
            return new ChainDefinitionSectionMetaSource();
        }
    

    ChainDefinitionSectionMetaSource 代码参考

    (4)启动方法注解

    在方法上可以使用注解来开启权限控制,实际上是AOP的实现之一

      /**
         * 开启aop注解支持
         *
         * @param securityManager
         * @return
         */
        @Bean
        public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(org.apache.shiro.mgt.SecurityManager securityManager) {
            AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
            authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
            return authorizationAttributeSourceAdvisor;
        }
    

    文章参考

    Springboot与shiro整合遇到的坑

    106.2 Spring Boot之Shiro无状态(2)【从零开始学Spring Boot】

    spring boot 2.0 集成 shiro 和 pac4j cas单点登录

    相关文章

      网友评论

        本文标题:shiro(15)-springboot2.x整合shiro(无

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