如何解决实现Spring Security+JWT认证后的Bean依赖问题
在实施 Spring Security + JWT 身份验证后,我的应用程序无法构建。有关控制器和服务的测试失败。当我尝试构建应用程序时,我会通过来自控制器和服务的测试收到此类信息:
java.lang.IllegalStateException
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException
Caused by: org.springframework.beans.factory.BeanCreationException
Caused by: org.springframework.beans.factory.NoSuchBeanDeFinitionException
在实施 Spring Security + JWT 身份验证之前,一切正常。
我寻找解决方案并尝试:
- 将@Autowired 和字段替换为@Bean 和类中关于 Spring Security + JWT 认证的方法
- 在关于 Spring Security + JWT 认证的类中实现 @ComponentScan
- 在关于 Spring Security + JWT 认证的类中添加 @Lazy 和 @Autowired
因为下面的注入有问题:
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Lazy
@Autowired(required = true)
private ReaderPrincipalDetailsService readerPrincipalDetailsService;
@Lazy
@Autowired(required = true)
private JwtRequestFilter jwtRequestFilter;
现在,在这些更正之后,当我尝试运行 1 个失败的测试时,重要的日志看起来像这样(如果有这样的需要,我可以将其全部附上):
2021-02-05 10:11:09.530 WARN 6980 --- [ main] o.s.w.c.s.GenericWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: **Error creating bean with name 'volumeAdapter': Unsatisfied dependency expressed through field 'volumeService'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'volumeService'**: Injection of persistence dependencies Failed; nested exception is org.springframework.beans.factory.NoSuchBeanDeFinitionException: No qualifying bean of type 'javax.persistence.EntityManagerFactory' available
Description:
Field volumeService in com.kodilla.librarybackend.adapter.VolumeAdapter required a bean of type 'javax.persistence.EntityManagerFactory' that Could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Consider defining a bean of type 'javax.persistence.EntityManagerFactory' in your configuration.
2021-02-05 10:11:09.787 ERROR 6980 --- [ main] o.s.test.context.TestContextManager : Caught exception while allowing TestExecutionListener [org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener@1fa268de] to prepare test instance [com.kodilla.librarybackend.controller.GenreControllerTest@57c47a9e]
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'volumeAdapter': Unsatisfied dependency expressed through field 'volumeService'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'volumeService': Injection of persistence dependencies Failed; nested exception is org.springframework.beans.factory.NoSuchBeanDeFinitionException: No qualifying bean of type 'javax.persistence.EntityManagerFactory' available
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'volumeService': Injection of persistence dependencies Failed; nested exception is org.springframework.beans.factory.NoSuchBeanDeFinitionException: No qualifying bean of type 'javax.persistence.EntityManagerFactory' available
Caused by: org.springframework.beans.factory.NoSuchBeanDeFinitionException: No qualifying bean of type 'javax.persistence.EntityManagerFactory' available
这是我关于身份验证的课程:
@EnableWebSecurity
@Component
@ComponentScan(basePackages = {"com.kodilla.librarybackend"})
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Lazy
@Autowired(required = true)
private ReaderPrincipalDetailsService readerPrincipalDetailsService;
@Lazy
@Autowired(required = true)
private JwtRequestFilter jwtRequestFilter;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(readerPrincipalDetailsService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests().antMatchers("/authenticate").permitAll()
.anyRequest().authenticated()
.and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtRequestFilter,UsernamePasswordAuthenticationFilter.class);
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception{
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();
}
}
@Service
@ComponentScan(basePackages = {"com.kodilla.librarybackend"})
public class ReaderPrincipalDetailsService implements UserDetailsService {
@Lazy
@Autowired
private ReaderRepository readerRepository;
@Override
public UserDetails loadUserByUsername(String emailAddress) throws UsernameNotFoundException {
return readerRepository.findFirstByEmailAddress(emailAddress);
}
}
@Service
public class JwtUtil {
public JwtUtil() {
}
private String SECRET_KEY = "secret";
public String extractUserName(String token){
return extractClaim(token,Claims::getSubject);
}
public Date extractExpiration(String token){
return extractClaim(token,Claims::getExpiration);
}
public <T> T extractClaim(String token,Function<Claims,T> claimsResolver){
final Claims claims = extractAllClaims(token);
return claimsResolver.apply(claims);
}
private Claims extractAllClaims (String token){
return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();
}
private Boolean isTokenExpired (String token){
return extractExpiration(token).before(new Date());
}
public String generatetoken(UserDetails userDetails){
Map <String,Object> claims = new HashMap<>();
return createtoken(claims,userDetails.getUsername());
}
private String createtoken (Map<String,Object>claims,String subject){
return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10))
.signWith(SignatureAlgorithm.HS256,SECRET_KEY).compact();
}
public Boolean validatetoken(String token,UserDetails userDetails){
final String readerName = extractUserName(token);
return (readerName.equals(userDetails.getUsername()) && isTokenExpired(token));
}
}
@Component
@ComponentScan(basePackages = {"com.kodilla.librarybackend"})
public class JwtRequestFilter extends OncePerRequestFilter {
@Lazy
@Autowired
private ReaderPrincipalDetailsService readerPrincipalDetailsService;
@Lazy
@Autowired
private JwtUtil jwtUtil;
@Override
protected void doFilterInternal(HttpServletRequest request,HttpServletResponse response,FilterChain filterChain)
throws servletexception,IOException {
final String authorizationHeader = request.getHeader("Authorization");
String emailAddress = null;
String jwt = null;
if(authorizationHeader != null && authorizationHeader.startsWith("Bearer ")){
jwt = authorizationHeader.substring(7);
emailAddress = jwtUtil.extractUserName(jwt);
}
if(emailAddress != null && SecurityContextHolder.getContext().getAuthentication() == null){
UserDetails userDetails = this.readerPrincipalDetailsService.loadUserByUsername(emailAddress);
if(jwtUtil.validatetoken(jwt,userDetails)){
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails,null,userDetails.getAuthorities());
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
filterChain.doFilter(request,response);
}
}
public class AuthenticationRequest {
private String emailAddress;
private String password;
public AuthenticationRequest(String emailAddress,String password) {
this.emailAddress = emailAddress;
this.password = password;
}
public AuthenticationRequest() {
}
public String getemailAddress() {
return emailAddress;
}
public String getpassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
public class AuthenticationResponse {
private final String jwt;
public AuthenticationResponse(String jwt) {
this.jwt = jwt;
}
public String getJwt() {
return jwt;
}
}
以及这些关于当前错误的:
@Component
public class VolumeAdapter {
@Autowired
private VolumeService volumeService;
private static final Logger LOGGER = LoggerFactory.getLogger(VolumeAdapter.class);
public List<Volume> createallGoogleVolumeList(List<VolumeDto> volumeDtoList){
LOGGER.info("Google books adapter starts...");
return volumeDtoList.stream().map(v -> {
return new Volume(v.getTitle(),v.getAuthors(),v.getPublishedDate(),v.getDescription());
}).collect(Collectors.toList());
}
public List <Volume> createSpecificVolume(List <VolumeDto> volumeDtoList){
LOGGER.info("Specific google book adapter is looking for requested book");
return volumeDtoList.stream().map(v -> {
return new Volume(v.getTitle(),v.getDescription());
}).collect(Collectors.toList());
}
}
@Service
public class VolumeService {
@Autowired
private GoogleBooksClient googleBooksClient;
@Autowired
private VolumeRepository volumeRepository;
@Autowired
private CartRepository cartRepository;
@Autowired
private VolumeMapper volumeMapper;
@PersistenceContext
private EntityManager entityManager;
@Autowired
private VolumeAdapter volumeAdapter;
private static final Logger LOGGER = LoggerFactory.getLogger(VolumeService.class);
private Set<Volume> volumes;
private static VolumeService volumeService;
public static VolumeService getInstance() {
if (volumeService == null) {
volumeService = new VolumeService();
}
return volumeService;
}
public Set<Volume> getBooks() {
return new HashSet<>(volumes);
}
public List <Volume> fetchSpecifiedGoogleBook(String book){
LOGGER.info("Fetching Google Book with requested typo:"+ book);
return volumeAdapter.createSpecificVolume(googleBooksClient.getSpecifiedGoogleBooks(book));
}
public void addBook(Volume volume) {
this.volumes.add(volume);
}
public CartBookAdderDto putFoundVolumeInCart (Volume foundVolume,Long cartId){
LOGGER.info("Putting found volume in cart started");
Cart cart = cartRepository.findCartById(cartId);
LOGGER.info("Cart: " + cart.toString() + " selected.");
LOGGER.info("Volume: " + foundVolume.getTitle() + " adding to cart started");
Volume volumePutInCart = new Volume(foundVolume.getTitle(),foundVolume.getAuthors(),foundVolume.getPublishedDate(),foundVolume.getDescription());
List <Volume> volumeList = new ArrayList<>();
volumeList.add(volumePutInCart);
cart.setBooks(volumeList);
LOGGER.info("Volume added to cart");
return new CartBookAdderDto(cartId,volumeMapper.mapToBookDtoList((volumeList)));
}
/*public VolumeDto getBookPutInCart(CartBookAdderDto cartBookAdderDto){
LOGGER.info("Getting books put in cart started");
if(putFoundVolumeInCart(volumeMapper.mapToBook(cartBookAdderDto.getBookDto()),volumeMapper.mapToBook(cartBookAdderDto.getBookDto()).toString(),cartBookAdderDto.getCartId()) != null){
VolumeDto bookPutInCart = putFoundVolumeInCart(volumeMapper.mapToBook(cartBookAdderDto.getBookDto()),cartBookAdderDto.getCartId()).getBookDto();
LOGGER.info(bookPutInCart + " will be put in cart");
return bookPutInCart;
}
else{
LOGGER.info("Putting book in Cart Failed");
}
return new VolumeDto();
}*/
/*public List<Volume> getAvaiabletoRentBooks(boolean rented) {
LOGGER.info("Getting books avaiable to rent");
List<Volume> volumeList = volumeRepository.findAll();
return volumeList.stream()
.filter(book -> book.isRented() == false)
.collect(Collectors.toList());
}*/
/*public List<Volume> getAlreadyRentedBooks(boolean rented) {
LOGGER.info("Getting books already rented");
List<Volume> volumeList = volumeRepository.findAll();
return volumeList.stream()
.filter(book -> book.isRented() == true)
.collect(Collectors.toList());
}*/
public List<Volume> getBooksOfDefiniedTitleAndAuthor(String title,String authors) {
LOGGER.info("Getting books of:"+authors);
List<Volume> volumeList = volumeRepository.findAll();
return volumeList.stream()
.filter(book -> book.getTitle() == title)
.filter(book -> book.getAuthors() == authors)
.collect(Collectors.toList());
}
public Volume getBook(final Long id){
LOGGER.info("Getting book with id:"+id.toString());
return volumeRepository.getone(id);
}
@Transactional
public Volume createBook(final Volume volume){
LOGGER.info("Creating new book");
return volumeRepository.save(volume);
}
/*public void updateBook(final Long id){
LOGGER.info("Start of updating book with id:"+id.toString());
volumeRepository.updateBookSetRentedForId(true,id);
Book book = getBook(id);
entityManager.refresh(book);
LOGGER.info("Updating book with id:"+id.toString()+" finished");
}*/
@Transactional
public void deleteBook(final Long id){
LOGGER.info("Deleting book with id:"+id.toString());
volumeRepository.deleteById(id);
}
}
抱歉发这么长的帖子:),我想附上所有可能有用的信息
有人知道那里发生了什么吗? :)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。