springboot+shiro is not eligible for getting processed by all BeanPostProcessors

项目背景:

服务基于springboot搭建,shiro做认证鉴权,本地启动正常,打包正常,服务器启动正常,采用jenkins打包部署服务,偶尔出现问题

原因分析:

因为问题是偶现的,当时觉得是环境问题导致,有的服务器可以启动,有的服务器无法启动,报错是偶现的

初步排查了环境,jdk,port,mvn,jenkins服务器配置,都没问题

排查日志:

2020-05-13 22:07:48.066  INFO 876 --- [main] com.*.SpringBootApplication               : Starting SpringBootApplication v1.0.0.0-SNAPSHOT on server with PID 876 (/opt/server/ms-server.jar started by root in /opt/server)
2020-05-13 22:07:48.072 DEBUG 876 --- [main] com.*.SpringBootApplication               : Running with Spring Boot v2.2.2.RELEASE, Spring v5.2.2.RELEASE
2020-05-13 22:07:48.072  INFO 876 --- [main] com.*.SpringBootApplication               : The following profiles are active: dev
2020-05-13 22:07:51.969  INFO 876 --- [main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
2020-05-13 22:07:51.976  INFO 876 --- [main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Elasticsearch repositories in DEFAULT mode.
2020-05-13 22:07:52.113  INFO 876 --- [main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 114ms. Found 0 Elasticsearch repository interfaces.
2020-05-13 22:07:52.134  INFO 876 --- [main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
2020-05-13 22:07:52.134  INFO 876 --- [main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Reactive Elasticsearch repositories in DEFAULT mode.
2020-05-13 22:07:52.177  INFO 876 --- [main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 42ms. Found 0 Reactive Elasticsearch repository interfaces.
2020-05-13 22:07:52.240  INFO 876 --- [main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
2020-05-13 22:07:52.284  INFO 876 --- [main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Redis repositories in DEFAULT mode.
2020-05-13 22:07:52.357  INFO 876 --- [main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 44ms. Found 0 Redis repository interfaces.
2020-05-13 22:07:53.633  INFO 876 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'webConfig' of type [com.*.config.WebConfig$$EnhancerBySpringCGLIB$$323d34e4] 
																							is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-05-13 22:07:54.038  INFO 876 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration] 
																							is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-05-13 22:07:54.442  INFO 876 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'redisConfig' of type [com.*.base.redis.RedisConfig$$EnhancerBySpringCGLIB$$4b225e87
 is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-05-13 22:07:54.479  INFO 876 --- [main] trationDelegate$BeanPostProcessorChecker : Bean 'shiroConfig' of type [com.*.config.ShiroConfig$$EnhancerBySpringCGLIB$$e73c6be1]
 is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2020-05-13 22:07:54.543  WARN 876 --- [main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: 
org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'objectMapperConfigurer' defined in class path resource [springfox/documentation/spring/web/SpringfoxWebMvcConfiguration.class]: 
						BeanPostProcessor before instantiation of bean failed;
 						nested exception is org.springframework.beans.factory.BeanCreationException:
 						Error creating bean with name 'druidConfig' defined in URL [jar:file:/opt/server/ms-server.jar!/BOOT-INF/classes!/com/*/config/DruidConfig.class]: 
 						BeanPostProcessor before instantiation of bean failed; 
 						nested exception is org.springframework.beans.factory.BeanCreationException: 
 						Error creating bean with name 'authorizationAttributeSourceAdvisor' defined in class path resource [com/*/config/ShiroConfig.class]: 
 						Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: 
 						Failed to instantiate [org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor]: 
 						Factory method 'authorizationAttributeSourceAdvisor' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: 
 						Error creating bean with name 'securityManager' defined in class path resource [com/*/config/ShiroConfig.class]: 
 						Bean instantiation via factory method failed; 
 						nested exception is org.springframework.beans.BeanInstantiationException: 
 						Failed to instantiate [org.apache.shiro.mgt.SecurityManager]:
 						Factory method 'securityManager' threw exception; 
 						nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: 
 						Error creating bean with name 'customRealm': 
 						Unsatisfied dependency expressed through field 'managerBiz'; 
 						nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: 
 						Error creating bean with name 'shirFilter' defined in class path resource [com/*/config/ShiroConfig.class]: 
 						Unsatisfied dependency expressed through method 'shirFilter' parameter 0; 
 						nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: 
 						Error creating bean with name 'securityManager': Requested bean is currently in creation: 
 						Is there an unresolvable circular reference?
2020-05-13 22:07:54.556  INFO 876 --- [main] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2020-05-13 22:07:54.571 ERROR 876 --- [main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

The dependencies of some of the beans in the application context form a cycle:

   objectMapperConfigurer defined in class path resource [springfox/documentation/spring/web/SpringfoxWebMvcConfiguration.class]
      ↓
   druidConfig defined in URL [jar:file:/opt/server/ms-server.jar!/BOOT-INF/classes!/com/*/config/DruidConfig.class]
      ↓
   authorizationAttributeSourceAdvisor defined in class path resource [com/*/config/ShiroConfig.class]
┌─────┐
|  securityManager defined in class path resource [com/*/config/ShiroConfig.class]
↑     ↓
|  customRealm (field private com.*.basic.biz.IXBiz com.*.basic.security.BaseAuthRealm.managerBiz)
↑     ↓
|  shirFilter defined in class path resource [com/*/config/ShiroConfig.class]
└─────┘


排查发现 虽然是偶现的打包问题 本地起服务虽然可以起来 但这里报循环依赖问题 查看日志发现

Failed to instantiate [org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor]: 
Factory method 'authorizationAttributeSourceAdvisor' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'securityManager' defined in class path resource [com/*/config/ShiroConfig.class]: 

┌─────┐
|  securityManager defined in class path resource [com/*/config/ShiroConfig.class]
↑     ↓
|  customRealm (field private com.*.basic.biz.IXBiz com.*.basic.security.BaseAuthRealm.managerBiz)
↑     ↓
|  shirFilter defined in class path resource [com/*/config/ShiroConfig.class]
└─────┘

在此处创建Bean失败了~

 

问题定位:

附上问题代码:

package com.*.config;

import com.*.basic.security.BaseAuthRealm;
import org.apache.shiro.mgt.SecurityManager;
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.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

	@Value("${path}")
	private String path;

	@Bean
	public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		// 必须设置 SecurityManager
		shiroFilterFactoryBean.setSecurityManager(securityManager);
		// setLoginUrl 如果不设置值,默认会自动寻找Web工程根目录下的"/login.jsp"页面 或 "/login" 映射
		shiroFilterFactoryBean.setLoginUrl(path + "/index");
		// 设置无权限时跳转的 url;
		shiroFilterFactoryBean.setUnauthorizedUrl(path + "/404.html");

		// 设置拦截器
		Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
		// 游客,开发权限
		filterChainDefinitionMap.put("/static/**", "anon");
		filterChainDefinitionMap.put("/html/**", "anon");
		// 开放登陆接口
		filterChainDefinitionMap.put(path + "/index", "anon");
		// 其余接口一律拦截
		// 主要这行代码必须放在所有权限设置的最后,不然会导致所有 url 都被拦截
		filterChainDefinitionMap.put(path + "/**", "authc");

		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
		return shiroFilterFactoryBean;
	}


	/**
	 * 注入 securityManager
	 */
	@Bean
	public SecurityManager securityManager() {
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		// 设置realm
		securityManager.setRealm(customRealm());
		return securityManager;
	}


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

	/**
	 * 自定义身份认证 realm;
	 * 必须写这个类,并加上 @Bean 注解,目的是注入 自定义Realm, 否则会影响 自定义Realm类 中其他类的依赖注入
	 */
	@Bean
	public BaseAuthRealm customRealm() {
		return new BaseAuthRealm();
	}
}

此处问题代码:

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

原因分析:

这个bean注册时,调用了securityManager()方法,此处这个方法被多次调用,原则上应该是引用而不是新建一个Bean,此处Bean应该是单例的

代码修复:

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

附上修复后的代码:

package com.*.config;

import com.*.basic.security.BaseAuthRealm;
import org.apache.shiro.mgt.SecurityManager;
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.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

	@Value("${path}")
	private String path;

	@Bean
	public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		// 必须设置 SecurityManager
		shiroFilterFactoryBean.setSecurityManager(securityManager);
		// setLoginUrl 如果不设置值,默认会自动寻找Web工程根目录下的"/login.jsp"页面 或 "/login" 映射
		shiroFilterFactoryBean.setLoginUrl(path + "/index");
		// 设置无权限时跳转的 url;
		shiroFilterFactoryBean.setUnauthorizedUrl(path + "/404.html");

		// 设置拦截器
		Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
		// 游客,开发权限
		filterChainDefinitionMap.put("/static/**", "anon");
		filterChainDefinitionMap.put("/html/**", "anon");
		// 开放登陆接口
		filterChainDefinitionMap.put(path + "/index", "anon");
		// 其余接口一律拦截
		// 主要这行代码必须放在所有权限设置的最后,不然会导致所有 url 都被拦截
		filterChainDefinitionMap.put(path + "/**", "authc");

		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
		return shiroFilterFactoryBean;
	}


	/**
	 * 注入 securityManager
	 */
	@Bean
	public SecurityManager securityManager() {
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		// 设置realm
		securityManager.setRealm(customRealm());
		return securityManager;
	}


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

	/**
	 * 自定义身份认证 realm;
	 * 必须写这个类,并加上 @Bean 注解,目的是注入 自定义Realm, 否则会影响 自定义Realm类 中其他类的依赖注入
	 */
	@Bean
	public BaseAuthRealm customRealm() {
		return new BaseAuthRealm();
	}
}

问题解决     jenkins部署/本地打包/mvn都不会出现问题了~

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: springboot+shiro+jwt 是一种常见的后端技术组合,其中 springboot 是一个基于 Spring 框架的快速开发框架,shiro 是一个安全框架,用于身份验证、授权和加密等功能,jwt 是一种基于 token 的身份验证机制,可以用于前后端分离的应用中。这种技术组合可以帮助开发者快速搭建安全可靠的后端服务。 ### 回答2: Springboot是一个开源的Java开发框架,是基于Spring框架的远程服务器控制技术方案,是现代化的全栈框架,集成丰富,提供了大量的开箱即用的组件,可以大大简化开发人员的开发工作。 Shiro是一个强大的轻量级安全框架,支持用户身份识别、密码加密、权限控制、会话管理等一系列安全功能,被广泛应用于JavaWeb开发中。 JWT(JSON Web Token)是一种开放标准(RFC 7519),定义了一种简洁的、自包含的方式,用于通信双方之间以JSON对象的形式安全地传递信息。JWT可以用于状态管理和用户身份认证等场景。 在使用SpringBoot开发Web应用过程中,Shiro与JWT可以同时用于用户身份认证和权限控制。Shiro提供了一系列的身份识别、密码加密、权限控制、会话管理等功能,而JWT则可以实现无状态的身份认证。使用Shiro和JWT,可以有效地保护Web应用的安全,避免被恶意攻击者利用。 具体而言,使用Shiro和JWT可以将用户认证的主要逻辑统一在一起,实现更加优雅的认证和授权过程。同时,这样的组合也可以避免一些常见的安全漏洞,比如会话劫持、XSS攻击、CSRF等。 在实际开发中,使用SpringBoot Shiro JWT可以方便地进行二次开发,进一步优化开发成本和提高开发效率。同时,使用这个组合可以让开发者更好地专注于业务逻辑的开发,而无需关注安全问题,从而提高开发质量和开发人员的工作效率。 ### 回答3: Spring Boot是一种基于Spring框架的快速开发微服务的工具,能够使开发者可以快速构建基于Spring的应用程序。而Shiro是一个强大易用的Java安全框架,可用于身份验证、权限控制、加密等。JWT(JSON Web Token)是一种基于JSON的安全令牌,可用于在客户端和服务器之间传递信息。 在使用Spring Boot开发Web应用程序时,通常需要进行用户身份验证和访问控制,这时候就可以使用Shiro来实现这些功能。同时,由于Web应用程序需要跨域访问,因此使用JWT可以方便地实现身份验证和授权的管理。 在使用Spring BootShiro时,可以使用JWT作为身份验证和授权的管理工具。此时,需要进行以下几个步骤: 1.添加Shiro和JWT的依赖 在Spring Boot项目中,可以通过Maven或Gradle等工具添加Shiro和JWT的依赖。例如,可以添加以下依赖: <!-- Shiro依赖 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.7.0</version> </dependency> <!-- JWT依赖 --> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> 2.配置ShiroSpring Boot项目中,可以通过在application.properties或application.yml文件中进行Shiro的配置。例如,可以配置以下内容: # Shiro配置 shiro: user: loginUrl: /login # 登录页面URL jwt: secret: my_secret # JWT加密密钥 expiration: 1800000 # JWT过期时间,单位为毫秒,默认30分钟 3.创建Shiro的Realm 在Shiro中,Realm是用于从应用程序中获取安全数据(如用户、角色和权限)的组件。因此,需要创建Shiro的Realm,用于管理用户的认证和授权。 例如,可以创建一个自定义的Realm,其中包括从数据库中获取用户和角色的方法: public class MyRealm extends AuthorizingRealm { @Autowired private UserService userService; /** * 认证,验证用户身份 */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String username = (String) token.getPrincipal(); User user = userService.findByUsername(username); if (user == null) { throw new UnknownAccountException("用户名或密码错误"); } String password = user.getPassword(); return new SimpleAuthenticationInfo(user.getUsername(), password, getName()); } /** * 授权,验证用户的访问权限 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String username = (String) principals.getPrimaryPrincipal(); User user = userService.findByUsername(username); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); Set<String> roles = user.getRoles(); authorizationInfo.setRoles(roles); Set<String> permissions = user.getPermissions(); authorizationInfo.setStringPermissions(permissions); return authorizationInfo; } } 4.使用JWT进行身份验证和授权管理 在Spring Boot应用程序中,使用Shiro和JWT来进行身份验证和授权管理的流程大致如下: 4.1 前端用户进行登录操作,将用户名和密码发送到后台服务。 4.2 后台服务进行身份验证,将用户身份信息生成JWT并返回给前端。 4.3 前端保存JWT,并在后续的请求中将其发送到后台服务。 4.4 后台服务验证JWT的有效性,并根据用户的角色和权限信息进行访问控制。 综上所述,Spring BootShiro和JWT可以很好地配合使用,实现Web应用程序的身份验证和授权管理。这种组合方案可以提高开发效率和系统安全性,同时也适用于微服务架构中对身份验证和授权的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值