zoukankan      html  css  js  c++  java
  • Spring Boot整合shiro出现UnavailableSecurityManagerException

      spring boot默认使用spring security,spring security自然不用说是一个强大的安全框架,但是用惯了shiro,一时半会用不来spring security,所以要在spring boot中自己整合shiro。说到整合shiro,网上也是有不少教程的,但是网上的教程也不是一定是对的,可能有版本等各种问题,所以说还是要自己来动手做一遍。

      在我动手整合的时候出现UnavailableSecurityManagerException的错误:

    2016-12-24 10:58:56.787 ERROR 7916 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [org.apache.shiro.UnavailableSecurityManagerException: No SecurityManager accessible to the calling code, either bound to the org.apache.shiro.util.ThreadContext or as a vm static singleton.  This is an invalid application configuration.] with root cause
    
    org.apache.shiro.UnavailableSecurityManagerException: No SecurityManager accessible to the calling code, either bound to the org.apache.shiro.util.ThreadContext or as a vm static singleton.  This is an invalid application configuration.

    spring整合shiro出现UnavailableSecurityManagerException在网上查出的问题都是没有配置DelegatingFilterProxy或者DelegatingFilterProxy的配置顺序错了,对应的解决办法就是在web.xml上添加DelegatingFilterProxy。

    <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <async-supported>true</async-supported>
        <init-param>
                 <param-name>targetFilterLifecycle</param-name>
                 <param-value>true</param-value>
         </init-param>
    </filter>
    <filter-mapping>
        <filter-name>shiroFilter</filter-name>
        <url-pattern>/*</url-pattern>
     </filter-mapping>

    可是我们现在使用的spring boot啊,才不要再用回web.xml的配置文件呢。那到底怎么解决呢?

    我第一想法就是,使用FilterRegistrationBean注册一个DelegatingFilterProxy:

    @Bean
    public FilterRegistrationBean delegatingFilterProxy(){
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        DelegatingFilterProxy proxy = new DelegatingFilterProxy();
        proxy.setTargetFilterLifecycle(true);
        filterRegistrationBean.setFilter(proxy);
        return filterRegistrationBean;
    }

    跟上面一样,应该没问题吧?可这都是我的一厢情愿,出错了:

    org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'delegatingFilterProxy' is expected to be of type [javax.servlet.Filter] but was actually of type [org.springframework.boot.web.servlet.FilterRegistrationBean]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:378) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
        at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1082) ~[spring-context-4.3.3.RELEASE.jar:4.3.3.RELEASE]
        at org.springframework.web.filter.DelegatingFilterProxy.initDelegate(DelegatingFilterProxy.java:326) ~[spring-web-4.3.3.RELEASE.jar:4.3.3.RELEASE]
        at org.springframework.web.filter.DelegatingFilterProxy.initFilterBean(DelegatingFilterProxy.java:235) ~[spring-web-4.3.3.RELEASE.jar:4.3.3.RELEASE]
        at org.springframework.web.filter.GenericFilterBean.init(GenericFilterBean.java:199) ~[spring-web-4.3.3.RELEASE.jar:4.3.3.RELEASE]
        at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:279) ~[tomcat-embed-core-8.5.5.jar:8.5.5]
        at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:109) ~[tomcat-embed-core-8.5.5.jar:8.5.5]
        at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4572) [tomcat-embed-core-8.5.5.jar:8.5.5]
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5215) [tomcat-embed-core-8.5.5.jar:8.5.5]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [tomcat-embed-core-8.5.5.jar:8.5.5]
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1403) [tomcat-embed-core-8.5.5.jar:8.5.5]
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1393) [tomcat-embed-core-8.5.5.jar:8.5.5]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_25]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_25]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_25]
        at java.lang.Thread.run(Thread.java:745) [na:1.8.0_25]
    View Code

    看到下面这个错误行:

    at org.springframework.web.filter.DelegatingFilterProxy.initDelegate(DelegatingFilterProxy.java:326) ~[spring-web-4.3.3.RELEASE.jar:4.3.3.RELEASE]

    看到下面代码,我们大概可以知道,根据getTargetBeanName()来进行委派,而TargetBeanName是delegatingFilterProxy。

    诶,不对啊,我shiroFilter的beanName不是这个啊,明明是shiroFilter。

    protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
         Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);
         if (isTargetFilterLifecycle()) {
             delegate.init(getFilterConfig());
         }
         return delegate;
    }

    解决办法

    经过上面一大串推论,解决办法就是:

    @Bean
    public FilterRegistrationBean delegatingFilterProxy(){
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        DelegatingFilterProxy proxy = new DelegatingFilterProxy();
        proxy.setTargetFilterLifecycle(true);
        proxy.setTargetBeanName("shiroFilter");
        filterRegistrationBean.setFilter(proxy);
        return filterRegistrationBean;
    }
    
    @Bean("shiroFilter")
    public ShiroFilterFactoryBean shiroFilterFactoryBean() {
        ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();
        .......
        return filterFactoryBean;
    }

    没有写太多shiro的整合代码,只写了解决UnavailableSecurityManagerException问题的关键代码,如需要可以自行网上查找。

  • 相关阅读:
    拜访优达学城上海总部
    ipad pro 文章
    探寻阿里云服务器迈入2.0时代的技术要点
    体验阿里云SSD云盘+ECS(I/O优化)的性能
    在iOS中使用OpenSSL的Public Key 进行加密
    使用FIR.im发布自己的移动端APP
    使用AFNetWorking 实现以Basic Authentication方式获取access-token
    使用AFNetWorking读取JSON出现NSCocoaErrorDomain Code=3840的解决方法
    #听云博客大赛#如何在自己的App嵌入听云产品监控App性能
    给自己的XTC820摆拍一下。
  • 原文地址:https://www.cnblogs.com/ginponson/p/6217057.html
Copyright © 2011-2022 走看看