微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

实现Spring Security+JWT认证后的Bean依赖问题

如何解决实现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 身份验证之前,一切正常。

我寻找解决方案并尝试:

  1. 将@Autowired 和字段替换为@Bean 和类中关于 Spring Security + JWT 认证的方法
  2. 在关于 Spring Security + JWT 认证的类中实现 @ComponentScan
  3. 在关于 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 举报,一经查实,本站将立刻删除。