应用程序上下文中一些bean的依赖关系形成了一个循环:
authController defined in file [...\AuthController.class]
↓
userServiceImpl defined in file [...\UserServiceImpl.class]
↓
jwtManager defined in file [...\JwtManager.class]
┌─────┐
| securityConfig defined in file [...\SecurityConfig.class]
└─────┘
我试过用@Lazy,但没用。
当我尝试将构造函数更改为setter时,它会给我错误,例如:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userServiceImpl' defined in file [...\UserServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 3;
证券配置
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final Logger LOG = LoggerFactory.getLogger(getClass());
private UserDetailsService userService;
private PasswordEncoder bCryptPasswordEncoder;
private ObjectMapper mapper;
@Value("${app.security.jwt.keystore-location}")
private String keyStorePath;
@Value("${app.security.jwt.keystore-password}")
private String keyStorePassword;
@Value("${app.security.jwt.key-alias}")
private String keyAlias;
@Value("${app.security.jwt.private-key-passphrase}")
private String privateKeyPassphrase;
public SecurityConfig(UserDetailsService userService,
PasswordEncoder bCryptPasswordEncoder, ObjectMapper mapper) {
this.userService = userService;
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
this.mapper = mapper;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().disable().formLogin().disable()
.csrf().ignoringAntMatchers(API_URL_PREFIX, H2_URL_PREFIX)
.and()
.headers().frameOptions().sameOrigin() // for H2 Console
.and()
.cors()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, TOKEN_URL).permitAll()
.antMatchers(HttpMethod.DELETE, TOKEN_URL).permitAll()
.antMatchers(HttpMethod.POST, SIGNUP_URL).permitAll()
.antMatchers(HttpMethod.POST, REFRESH_URL).permitAll()
.antMatchers(HttpMethod.GET, PRODUCTS_URL).permitAll()
.mvcMatchers(HttpMethod.POST, "/api/v1/restaurants**")
.hasAuthority(RoleEnum.ADMIN.getAuthority())
.anyRequest().authenticated()
.and()
/* Filter based security configuration
.exceptionHandling().accessDeniedHandler(accessDeniedHandler)
.and()
.httpBasic()
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.addFilterBefore(failureHandler , BearerTokenAuthenticationFilter.class)
.addFilter(new LoginFilter(super.authenticationManager(), mapper))
.addFilter(new JwtAuthenticationFilter(super.authenticationManager()))
*/
.oauth2ResourceServer(oauth2ResourceServer -> oauth2ResourceServer.jwt(
jwt -> jwt.jwtAuthenticationConverter(getJwtAuthenticationConverter())))
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
private Converter<Jwt, AbstractAuthenticationToken> getJwtAuthenticationConverter() {
JwtGrantedAuthoritiesConverter authorityConverter = new JwtGrantedAuthoritiesConverter();
authorityConverter.setAuthorityPrefix(AUTHORITY_PREFIX);
authorityConverter.setAuthoritiesClaimName(ROLE_CLAIM);
JwtAuthenticationConverter converter = new JwtAuthenticationConverter();
converter.setJwtGrantedAuthoritiesConverter(authorityConverter);
return converter;
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(bCryptPasswordEncoder);
}
@Bean
@Override
protected UserDetailsService userDetailsService() {
return userService;
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH"));
//configuration.setAllowCredentials(true);
// For CORS response headers
configuration.addAllowedOrigin("*");
configuration.addAllowedHeader("*");
configuration.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
@Bean
public KeyStore keyStore() {
try {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream resourceAsStream = Thread.currentThread().getContextClassLoader()
.getResourceAsStream(keyStorePath);
keyStore.load(resourceAsStream, keyStorePassword.toCharArray());
return keyStore;
} catch (IOException | CertificateException | NoSuchAlgorithmException | KeyStoreException e) {
LOG.error("Unable to load keystore: {}", keyStorePath, e);
}
throw new IllegalArgumentException("Unable to load keystore");
}
@Bean
public RSAPrivateKey jwtSigningKey(KeyStore keyStore) {
try {
Key key = keyStore.getKey(keyAlias, privateKeyPassphrase.toCharArray());
if (key instanceof RSAPrivateKey) {
return (RSAPrivateKey) key;
}
} catch (UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException e) {
LOG.error("Unable to load private key from keystore: {}", keyStorePath, e);
}
throw new IllegalArgumentException("Unable to load private key");
}
@Bean
public RSAPublicKey jwtValidationKey(KeyStore keyStore) {
try {
Certificate certificate = keyStore.getCertificate(keyAlias);
PublicKey publicKey = certificate.getPublicKey();
if (publicKey instanceof RSAPublicKey) {
return (RSAPublicKey) publicKey;
}
} catch (KeyStoreException e) {
LOG.error("Unable to load private key from keystore: {}", keyStorePath, e);
}
throw new IllegalArgumentException("Unable to load RSA public key");
}
@Bean
public JwtDecoder jwtDecoder(RSAPublicKey rsaPublicKey) {
return NimbusJwtDecoder.withPublicKey(rsaPublicKey).build();
}
UserServiceImpl
@Service
public class UserServiceImpl implements UserService {
private final UserRepository repository;
private final UserTokenRepository userTokenRepository;
private final PasswordEncoder bCryptPasswordEncoder;
private final JwtManager tokenManager;
public UserServiceImpl(UserRepository repository, UserTokenRepository userTokenRepository,
PasswordEncoder bCryptPasswordEncoder, JwtManager tokenManager) {
this.repository = repository;
this.userTokenRepository = userTokenRepository;
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
this.tokenManager = tokenManager;
}
JWTManager JWTManager是一个自定义类,负责生成新的JWT。它使用来自auth0的java jwt库。通用域名格式。我使用公钥/私钥对令牌进行签名。
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Date;
import static java.util.stream.Collectors.toList;
import static the.postbooking.app.security.Constants.EXPIRATION_TIME;
import static the.postbooking.app.security.Constants.ROLE_CLAIM;
@Component
public class JwtManager {
private final RSAPrivateKey privateKey;
private final RSAPublicKey publicKey;
public JwtManager(RSAPrivateKey privateKey, RSAPublicKey publicKey) {
this.privateKey = privateKey;
this.publicKey = publicKey;
}
public String create(UserDetails principal) {
final long now = System.currentTimeMillis();
return JWT.create()
.withIssuer("The Post Booking-App")
.withSubject(principal.getUsername())
.withClaim(ROLE_CLAIM,
principal.getAuthorities().stream().map(GrantedAuthority::getAuthority)
.collect(toList()))
.withIssuedAt(new Date(now))
.withExpiresAt(new Date(now + EXPIRATION_TIME))
//.sign(Algorithm.HMAC512(SECRET_KEY.getBytes(StandardCharsets.UTF_8)));
.sign(Algorithm.RSA256(publicKey, privateKey));
}
}
AuthController用@RestController注释AuthController类,将其标记为REST控制器。然后,它使用了两个bean,UserService和PasswordEncoder,它们将在AuthController构造时被注入。
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.RestController;
import postbookingapp.api.*;
import the.postbooking.app.entity.UserEntity;
import the.postbooking.app.exception.InvalidRefreshTokenException;
import the.postbooking.app.service.UserService;
import javax.validation.Valid;
import static org.springframework.http.ResponseEntity.*;
@RestController
public class AuthController implements UserApi {
private final UserService service;
private final PasswordEncoder passwordEncoder;
public AuthController(UserService service, PasswordEncoder passwordEncoder) {
this.service = service;
this.passwordEncoder = passwordEncoder;
}
@Override
public ResponseEntity<SignedInUser> signIn(@Valid SignInReq signInReq) {
UserEntity userEntity = service.findUserByUsername(signInReq.getUsername());
if (passwordEncoder.matches(
signInReq.getPassword(),
userEntity.getPassword())) {
return ok(service.getSignedInUser(userEntity));
}
throw new InsufficientAuthenticationException("Unauthorized.");
}
@Override
public ResponseEntity<Void> signOut(@Valid RefreshToken refreshToken) {
service.removeRefreshToken(refreshToken);
return accepted().build();
}
@Override
public ResponseEntity<SignedInUser> signUp(@Valid User user) {
return status(HttpStatus.CREATED).body(service.createUser(user).get());
}
@Override
public ResponseEntity<SignedInUser> getAccessToken(@Valid RefreshToken refreshToken) {
return ok(service.getAccessToken(refreshToken)
.orElseThrow(InvalidRefreshTokenException::new));
}
}
尝试添加spring。主要的在
文件应用程序中允许循环引用=true
。属性
我正在使用JPA开发Spring Boot v1.4.2.RELEASE应用程序。 我定义了存储库接口和实现 存储库 A存储自定义 ARepositoryImpl公司 和一个服务AServiceImpl 我的应用程序不会以以下消息开始: 我遵循http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositorie
我试图创建一个jwt与Spring安全,但当我启动程序,我采取这个错误从Spring: İt也是一个spring web程序,因此该程序与控制器一起工作。此控制器用于创建带有登录名的jwt。以下是我的authController类: 这里是WebServiceConfig类: 以下是UserDetailsService: 谢谢你的帮助阿莱尔迪
几周前,我将Spring的版本从1.4.x.RELEASE升级到1.5.1.RELEASE。 突然之间,由于这个错误,启动Spring Boot服务成了一场斗争: “应用程序上下文中某些bean的依赖关系形成一个循环” 同样的代码,不同的版本 这很有趣,因为在我的本地环境(OSX)上,相同的代码通常都可以正常启动,但在Heroku上,在不同的部署上会随机失败(在类路径类解析上看起来是不同的顺序,由
当我运行我的应用程序时,我得到了下面显示的错误,即应用程序上下文中一些bean的依赖关系形成了一个循环。我不确定问题到底是从哪里来的。对于Spring Boot/Spring Security性来说还是相对较新的,所以如果您能在我的代码上提供任何提示,我们将不胜感激。 UserServiceImpl 安全配置
启动Spring Boot应用程序时,我遇到了一个错误。 现在,我想在DAO存储库中使用,因为Spring Boot不会自动创建。所以,我从EntityManagerFactory创建了bean并尝试在DAO类中自动装配它。 但我有以下错误: 我不明白为什么SessionFactory指的是FooDao类。 以下是代码示例: 食物ao.java Config.java 富。Java语言 测试应用程
问题内容: 我有2个项目,其中一个包含在另一个构建路径中,两个项目都有自己的应用程序上下文来定义他的bean。 我想管理全局事务,因此我必须在一个应用程序上下文中同时导入这两个事务,但是我没有找到做到这一点的方法。 在不同的项目中可能有2个应用程序上下文,并将其中一个导入另一个。 如果没有可能,那将是最佳解决方案? 我认为成为1中的2个项目。 问题答案: 是的,可以导入;在您的一个appconte