【发布时间】: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