2013-11-07 4 views
0

Я пытаюсь использовать Shiro 1.2.2 с моим SpringMVC 3.2.3 Я видел несколько примеров того, как настроить Shiro с помощью ini-файлов. Но мы используем JavaConfig, и я нашел только один частичный пример. У меня есть несколько @Configuration файлов:Конфигурация SpringMVC, Shiro и Java

public class EdmWebInitializer implements WebApplicationInitializer { 

    private static final String DISPATCHER_SERVLET_NAME = "dispatcher"; 
    private static final String DISPATCHER_SERVLET_MAPPING = "/*"; 

    @Override 
    public void onStartup(ServletContext servletContext) throws ServletException { 
     AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext(); 
    root.scan("com.company.config"); 
    root.register(EdmConfiguration.class, SecurityConfig.class); 
    servletContext.addListener(new ContextLoaderListener(root)); 

    ServletRegistration.Dynamic appServlet = servletContext.addServlet(DISPATCHER_SERVLET_NAME, 
      new DispatcherServlet(root)); 
    appServlet.setLoadOnStartup(1); 

    Set<String> mappingConflicts = appServlet.addMapping(DISPATCHER_SERVLET_MAPPING); 
    servletContext 
      .addFilter("shiroFilter", new DelegatingFilterProxy("shiroFilter", root)) 
      .addMappingForUrlPatterns(null, false, DISPATCHER_SERVLET_MAPPING); 

    servletContext.addFilter("Spring OpenEntityManagerInViewFilter", 
      org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.class).addMappingForUrlPatterns(
      null, false, "/*"); 

Мои бобы определены здесь:

@Configuration 
@EnableWebMvc 
@ComponentScan(basePackages = { "com.company.service", "com.company.utility", 
     "com.company.controller", "com.company.utility.startup", 
     "com.company.security", "com.company.security.model" }) 
@EnableTransactionManagement 
@ImportResource({ "classpath:applicationContext.xml"}) 
@PropertySource({ "classpath:application.properties", "classpath:mail.properties" }) 
public class EdmConfiguration extends WebMvcConfigurationSupport { 


    @Resource 
    private Environment environment; 

    @Autowired 
    private org.apache.shiro.web.mgt.WebSecurityManager securityManager; 

    @Bean 
    public DataSource dataSource() { 
     BoneCPDataSource dataSource = new BoneCPDataSource(); 

    ... 
     return dataSource; 
    } 

    @Bean 
    public JpaTransactionManager transactionManager() throws ClassNotFoundException { 
     JpaTransactionManager transactionManager = new JpaTransactionManager(); 

     transactionManager.setEntityManagerFactory(entityManagerFactoryBean().getObject()); 

     return transactionManager; 
    } 

    @Bean 
    public DelegatingFilterProxy springSecurityFilterChain() { 
     return new DelegatingFilterProxy(); 
    } 

    @Bean 
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() throws ClassNotFoundException { 
     LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean(); 

     entityManagerFactoryBean.setDataSource(dataSource()); 
     entityManagerFactoryBean.setPackagesToScan(environment 
       .getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN)); 
     entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistence.class); 

     Properties jpaProperties = new Properties(); 
     ... 
     entityManagerFactoryBean.setJpaProperties(jpaProperties); 

     return entityManagerFactoryBean; 
    } 

    @Bean 
    public PersistenceExceptionTranslator exTranslator() { 
     return new HibernateExceptionTranslator(); 
    } 

    @Bean(initMethod = "init") 
    public StartupListener startupListener() { 
     return new StartupListener(); 
    } 




    @Bean 
    public ContentNegotiationManagerFactoryBean contentNegotiationManager() { 
     Properties properties = new Properties(); 
     properties.setProperty("xml", "application/xml"); 
     properties.setProperty("json", "application/json"); 
     properties.setProperty("html", "application/html"); 

     ContentNegotiationManagerFactoryBean contentNegotiationManager = new ContentNegotiationManagerFactoryBean(); 
     contentNegotiationManager.setFavorParameter(true); 
     contentNegotiationManager.setMediaTypes(properties); 
     contentNegotiationManager.setDefaultContentType(MediaType.APPLICATION_JSON); 

     return contentNegotiationManager; 
    } 



    @Bean 
    public JavaMailSenderImpl mailSender() { 
     JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); 
     int port = Integer.parseInt(environment.getRequiredProperty("mail.smtp.socketFactory.port")); 
     mailSender.setHost(environment.getRequiredProperty("mail.smtp.host")); 
     mailSender.setPort(port); 
     mailSender.setUsername(environment.getRequiredProperty("mail.login.username")); 
     mailSender.setPassword(environment.getRequiredProperty("mail.login.password")); 

     Properties properties = new Properties(); 
     properties.setProperty("mail.smtp.auth", environment.getRequiredProperty("mail.smtp.auth")); 
     properties.setProperty("mail.smtp.starttls.enable", "true"); 
     mailSender.setJavaMailProperties(properties); 

     return mailSender; 
    } 


    @Bean 
    public VelocityEngine getVelocityEngine() throws VelocityException, IOException { 
     VelocityEngineFactory factory = new VelocityEngineFactory(); 
     Properties props = new Properties(); 
     props.put("resource.loader", "class"); 
     props.put("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); 
     factory.setVelocityProperties(props); 
     factory.setResourceLoaderPath("/com/edelweissco/dental/templates"); 
     factory.setPreferFileSystemAccess(false); 
     return factory.createVelocityEngine(); 
    } 

    @Bean 
    public StandardPasswordEncoder encoder() { 
     return new org.springframework.security.crypto.password.StandardPasswordEncoder(); 
    } 

    @Bean 
    public ShiroFilterFactoryBean shiroFilter() { 
     ShiroFilterFactoryBean shiroFilter = new org.apache.shiro.spring.web.ShiroFilterFactoryBean(); 
     shiroFilter.setSecurityManager(securityManager); 
     return shiroFilter; 
    } 

    @Bean 
    @DependsOn(value = "lifecycleBeanPostProcessor") 
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { 
     DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator(); 
     creator.setProxyTargetClass(true); // it's false by default 
     return creator; 
    } 

Я нарушил configuraton Shiro в свой собственный файл:

@Configuration 
public class SecurityConfig { 

    @Bean 
    public CustomSecurityRealm customSecurityRealm() { 
     return new CustomSecurityRealm(); 
    } 

    @Bean 
    public SaltAwareJdbcRealm saltAwareJdbcRealm() { 
     return new SaltAwareJdbcRealm(); 
    } 

    @Bean 
    public org.apache.shiro.authc.credential.DefaultPasswordService passwordService() { 
     return new DefaultPasswordService(); 
    } 

    @Bean 
    public TempFixPasswordMatcher passwordMatcher() { 
     TempFixPasswordMatcher tempFixPasswordMatcher = new TempFixPasswordMatcher(); 
     tempFixPasswordMatcher.setPasswordService(passwordService()); 
     return tempFixPasswordMatcher; 
    } 


    @Bean 
    public WebSecurityManager securityManager() { 
     DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); 
     securityManager.setRealm(saltAwareJdbcRealm()); 
     return securityManager; 
    } 

    @Bean 
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { 
     return new LifecycleBeanPostProcessor(); 
    } 

    @Bean 
    public MethodInvokingFactoryBean methodInvokingFactoryBean() { 
     MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean(); 
     methodInvokingFactoryBean.setStaticMethod("org.apache.shiro.SecurityUtils.setSecurityManager"); 
     methodInvokingFactoryBean.setArguments(new Object[]{ securityManager() }); 
     return methodInvokingFactoryBean; 
    } 

    @Bean 
    @DependsOn(value = "lifecycleBeanPostProcessor") 
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { 
     return new DefaultAdvisorAutoProxyCreator(); 
    } 

    @Bean 
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() { 
     AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); 
     authorizationAttributeSourceAdvisor.setSecurityManager(securityManager()); 
     return authorizationAttributeSourceAdvisor; 
    } 

При попытке развернуть Я получаю исключения, такие как:

Это полная трассировка стека, которую я получаю, когда я удаляю @Transaction с моего O fficeService:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'menuService': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'menuRepository': Post-processing of the FactoryBean's object failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy68]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy68 
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:306) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1116) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:295) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:626) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479) 
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:389) 
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:294) 
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112) 
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4937) 
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5434) 
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) 
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901) 
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877) 
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:633) 
    at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1551) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:301) 
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:835) 
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:771) 
    at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:622) 
    at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:569) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:301) 
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:835) 
    at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:771) 
    at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1455) 
    at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:75) 
    at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1296) 
    at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1388) 
    at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:819) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:303) 
    at sun.rmi.transport.Transport$1.run(Transport.java:159) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at sun.rmi.transport.Transport.serviceCall(Transport.java:155) 
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535) 
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790) 
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918) 
    at java.lang.Thread.run(Thread.java:680) 
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'menuRepository': Post-processing of the FactoryBean's object failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy68]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy68 
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:165) 
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:102) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1454) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:306) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198) 
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:442) 
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:416) 
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:550) 
    at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:150) 
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) 
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:303) 
    ... 55 more 
Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy68]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy68 
    at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:217) 
    at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:111) 
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:477) 
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:362) 
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:322) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:409) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.postProcessObjectFromFactoryBean(AbstractAutowireCapableBeanFactory.java:1625) 
    at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:162) 
    ... 65 more 
Caused by: java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy68 
    at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:446) 
    at org.springframework.cglib.transform.TransformingClassGenerator.generateClass(TransformingClassGenerator.java:33) 
    at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25) 
    at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216) 
    at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:377) 
    at org.springframework.cglib.proxy.Enhancer.create(Enhancer.java:285) 
    at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:205) 
    ... 72 more 
Nov 9, 2013 4:10:04 PM org.apache.catalina.core.ApplicationContext log 
INFO: Closing Spring root WebApplicationContext 
+0

разместим ваш '' MenuRepository' и классы MenuService'. –

ответ

3

Вероятно, у вас есть какие-то @RequiresAuthentication или @RequiresRole аннотаций на классах обслуживания. Чтобы включить их, Shiro (Spring) должен проксировать созданные им бобы. Он делает это с фасолью DefaultAdvisorAutoProxyCreator. Однако этот компонент проксирует с проксими JDK, которые создают прокси на основе интерфейсов, а не на базовых классах.

Например, Spring имеет прокси OfficeService, он создаст экземпляр java.lang.reflect.Proxy, который обертывает bean-компонент OfficeService. Если вы назовете getClass() на этот объект, он вернет что-то вроде com.sun.proxy.$Proxy64. Если ваш OfficeService реализует любые интерфейсы, этот объект будет экземпляром этих интерфейсов. Однако компонент не является экземпляром OfficeService, поэтому Spring не может использовать его как цель @Autowired.

Вместо этого вы должны сообщить Spring, чтобы использовать прокси CGLIB. Вы можете сделать это, изменив конфиг здесь

@Bean 
@DependsOn(value = "lifecycleBeanPostProcessor") 
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { 
    DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator(); 
    creator.setProxyTargetClass(true); // it's false by default 
    return creator; 
} 

А добавление библиотеки CGLIB (баночки) для вашего пути к классам.


Обратите внимание, что если это не проблема Shiro, вам необходимо опубликовать остальную часть вашей конфигурации. Если вы выполняете какое-либо другое проксирование в своем контексте, вам нужно сделать что-то подобное, чтобы отключить прокси-серверы JDK.

Похоже, единственная вещь, которая может создать прокси является управление транзакциями, поэтому изменения в

@EnableTransactionManagement(proxyTargetClass = true) 
+0

У меня нет ни одного @RequiresRole или еще что-нибудь. Я просто пытаюсь получить конфигурацию Shiro, чтобы настроить ее. У меня есть cglib 2.2 в моих зависимостях уже для весеннего использования. Я добавил компонент DefaultAdvisorAutoProxyCreator, но все равно получаю ошибки. Я смог включить Shiro, заменив мой SecurityConfig сиро в applicationcontext.xml. Однако это не привело к созданию сеанса, вероятно, из-за фильтров сервлетов. И я действительно предпочел бы иметь всю мою конфигурацию на Java. Я обновляю свой пост с текущей конфигурацией. – sonoerin

+0

@sonoerin См. Мое редактирование. Для управления транзакциями также требуются прокси. Использует ли ваш класс 'OfficeService'' @ Transactional' для любого из его методов? Добавьте конфигурацию, которую я укажу в своем редактировании. –

+0

Я добавил EnableTransactionManagement (proxyTargetClass = true) в свой класс конфигурации, но это не изменило ситуацию.Когда я удалил @Transaction из своего OfficeService, я получаю другое исключение при развертывании: Caused by: org.springframework.aop.framework.AopConfigException: Не удалось создать подкласс класса CGLIB класса [class com.sun.proxy. $ Proxy68]: К распространенным причинам этой проблемы относятся использование конечного класса или невидимого класса; Вложенное исключение - это java.lang.IllegalArgumentException: не может подкласс класса класса com.sun.proxy. $ Proxy68 – sonoerin

Смежные вопросы