【问题标题】:Parameter 0 of constructor in AuthService required a bean of type 'springframework.security.crypto.password.PasswordEncoder' that could not be foundAuthService 中构造函数的参数 0 需要类型为 \'springframework.security.crypto.password.PasswordEncoder\' 的 bean,但找不到
【发布时间】:2023-02-07 07:02:54
【问题描述】:

您将在下面找到我认为你们需要的 2 个课程。如果需要更多信息,请告诉我。 授权服务

package com.r.reservationproject.services;

import com.r.reservationproject.dto.AuthenticationResponse;
import com.r.reservationproject.dto.RegisterRequest;
import com.r.reservationproject.domain.NotificationEmail;
import com.r.reservationproject.domain.User;
import com.r.reservationproject.domain.VerificationToken;
import com.r.reservationproject.dto.LoginRequest;
import com.r.reservationproject.exceptions.SpringReservationAccountException;
import com.r.reservationproject.repositories.UserRepo;
import com.r.reservationproject.repositories.VerificationTokenRepo;
import com.r.reservationproject.security.JwtProvider;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotBlank;
import java.time.Instant;
import java.util.Optional;
import java.util.UUID;

@Service
@AllArgsConstructor
@Transactional
// Contains logic to create username password authentication token and use authenticationManager to perform login
public class AuthService {
    private final PasswordEncoder passwordEncoder;
    private final UserRepo userRepo;
    private final VerificationTokenRepo verificationTokenRepo;
    private final MailService mailService;
    private final AuthenticationManager authenticationManager;
    private final JwtProvider jwtProvider;

    public void signup(RegisterRequest registerRequest) {
        User user = new User();
        user.setUsername(registerRequest.getUsername());
        user.setEmail(registerRequest.getEmail());
        user.setPassword(passwordEncoder.encode(registerRequest.getPassword()));
        user.setCreated(Instant.now());
        user.setEnabled(false);

        userRepo.save(user);

        String token = generateVerificationToken(user);
        mailService.sendMail(new NotificationEmail("Activeren account applicatie", user.getEmail(),
                "Bedankt voor het gebruiken van onze applicatie, om uw account te activeren vragen wij u om volgende link te klikken :" +
                        "http://localhost:8080/api/auth/accountVerification/" + token));
    }

    private String generateVerificationToken(User user) {
        String token = UUID.randomUUID().toString();
        VerificationToken verificationToken = new VerificationToken();
        verificationToken.setToken(token);
        verificationToken.setUser(user);

        verificationTokenRepo.save(verificationToken);
        return token;
    }

    public void verifyAccount(String token) {
        Optional<VerificationToken> verificationToken =  verificationTokenRepo.findByToken(token);
        verificationToken.orElseThrow(() -> new SpringReservationAccountException("Token is niet geldig"));
        fetchUserAndEnable(verificationToken.get());
    }

    public void fetchUserAndEnable(VerificationToken verificationToken) {
        @NotBlank(message = "Username is required") String username = verificationToken.getUser().getUsername();
        User user = userRepo.findByUsername(username).orElseThrow(() -> new SpringReservationAccountException("Gebruiker onbekend"));
        user.setEnabled(true);
        userRepo.save(user);
    }

    public AuthenticationResponse login(LoginRequest loginRequest) {
        Authentication authenticate = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));
        SecurityContextHolder.getContext().setAuthentication(authenticate);
        String token = jwtProvider.generateToken(authenticate);
        // to send this token we use a dto (authenticationresponse)
        return new AuthenticationResponse(token, loginRequest.getUsername());

    }
}

安全配置

package com.r.reservationproject.config;

import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@EnableWebSecurity
@AllArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    private final UserDetailsService userDetailsService;

    @Bean(BeanIds.AUTHENTICATION_MANAGER)
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests()
                .antMatchers("/api/auth/**")
                .permitAll()
                .anyRequest()
                .authenticated();
    }

    @Override
    public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder.userDetailsService(userDetailsService)
                .passwordEncoder(passwordEncoder());
    }
}

完整错误:


应用程序启动失败


描述:

com.r.reservationproject.services.AuthService 中构造函数的参数 0 需要一个类型为“org.springframework.security.crypto.password.PasswordEncoder”的 bean,但找不到。

行动:

考虑在您的配置中定义类型为“org.springframework.security.crypto.password.PasswordEncoder”的 bean。

我没有收到错误,因为我已经在 SecurityConfig 中定义了 Bean

非常感谢您的帮助!

【问题讨论】:

  • 您是否尝试过在公共范围内而不是包中声明该 bean?
  • @Stultuske 我对此很陌生,所以知道如何去做会很有帮助:)
  • 通过将关键字“public”放在“PasswordEncoder passwordEncoder()”前面,就像您对其他 Bean 所做的那样。如果你不知道该怎么做,你应该从学习基础知识开始,而不是尝试像 Spring 这样的高级框架
  • 哦,当然我已经试过了,我不确定你的意思
  • 我是 Spring 的新手,不是 Java ;)

标签: java spring spring-security


【解决方案1】:

尝试在您的 SecurityConfig 类中添加 @Configuration 注释

【讨论】:

    猜你喜欢
    • 2023-02-05
    • 1970-01-01
    • 2018-12-06
    • 1970-01-01
    • 2022-08-11
    • 2019-10-20
    • 2021-12-10
    • 2019-05-30
    • 2019-03-21
    相关资源
    最近更新 更多