我有这个错误,我不知道它可能是什么。我按照教程做用户身份验证,但当我尝试做身份验证时,它抛出了一个“错误的凭据”,但凭据是正确的。我正在使用MongoDB。
从教程中,我遵循这些步骤,它应该工作(其他用户确认他们这样做),但唯一的事情,我做了不同于教程是在“ClientEntity”类已经存在,我只是实现了我需要的。
用户退货:
ClientEntity(id=63166ddbe3ea6c4fffd70818, clientName=Test, clientCpf=000.000.000-00, clientEmail=teste2@example.com, clientPassword=2b598e4c0e79baf9dc9211ad303e7626, clientIsBlocked=false, clientBirthDate=1989-05-20, creditCards=[CreditCardEntity()], clientCategory=[ACAO, COMEDIA])
我的登录请求,我通过电子邮件和密码登录:
AccountCredentials: AccountCredentials(email=teste2@example.com, password=2b598e4c0e79baf9dc9211ad303e7626)
我知道问题出在**“authenticationManager.authenticate(新用户名密码authenticationToken(电子邮件,密码))中的那个类中;“**但我不知道怎么解决它,因为凭据是正确的
我的身份验证服务类:
@Service
public class AuthService {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtTokenProvider tokenProvider;
@Autowired
private ClientRepository repository;
public ResponseEntity signin(AccountCredentials data) {
try {
var email = data.getEmail();
var password = data.getPassword();
log.info("METODO SIGNIN, AccountCredentials: " + data);
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(email, password));
log.info("FOI AUTENTICADO!");
var user = repository.findByClientEmail(email);
log.info("O valor de User é: " + user);
var tokenResponse = new Token();
if (user != null) {
tokenResponse = tokenProvider.createAccessToken(email, user.getRoles());
} else {
throw new UsernameNotFoundException("Email " + email + " not found!");
}
return ResponseEntity.ok(tokenResponse);
} catch (Exception e) {
System.out.println(e.getMessage());
System.out.println(e.getCause());
System.out.println(e.getLocalizedMessage());
throw new BadCredentialsException("Invalid email/password supplied!");
}
}
public ResponseEntity refreshToken(String email, String refreshToken) {
var user = repository.findByClientEmail(email);
var tokenResponse = new Token();
if (user != null) {
tokenResponse = tokenProvider.refreshToken(refreshToken);
} else {
throw new UsernameNotFoundException("Email " + email + " not found!");
}
return ResponseEntity.ok(tokenResponse);
}
}
我的客户实体:
@Data
@Document(collection = "Client")
public class ClientEntity implements UserDetails, Serializable {
private static final long serialVersionUID = 1L;
@Id
private String id;
private String clientName;
private String clientCpf;
private String clientEmail;
private String clientPassword;
private boolean clientIsBlocked = false;
private LocalDate clientBirthDate;
private List<CreditCardEntity> creditCards;
private List<ClientCategoryEnum> clientCategory;
private List<Permission> permissions;
public List<String> getRoles() {
List<String> roles = new ArrayList<>();
for (Permission permission : permissions) {
roles.add("USER");
roles.add(permission.getDescription());
}
return roles;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.permissions;
}
@Override
public String getPassword() {
return this.clientPassword;
}
@Override
public String getUsername() {
return this.clientEmail;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
我的班级权限:
@Data
@Document(collection = "Roles")
public class Permission implements GrantedAuthority, Serializable {
private static final long serialVersionUID = 1L;
@Id
private Long id;
private String description;
@Override
public String getAuthority() {
return this.description;
}
}
我的安全配置:
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtTokenProvider tokenProvider;
/*
@Bean
public UserDetailsService userDetailsService() {
return super.userDetailsService();
}
*/
@Bean
public PasswordEncoder passwordEncoder() {
Map<String, PasswordEncoder> encoders = new HashMap<>();
encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
DelegatingPasswordEncoder passwordEncoder = new DelegatingPasswordEncoder("pbkdf2", encoders);
passwordEncoder.setDefaultPasswordEncoderForMatches(new Pbkdf2PasswordEncoder());
return passwordEncoder;
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic().disable()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(
"/auth/signin",
"/auth/refresh"
).permitAll()
.antMatchers("/api/movie_search/**").authenticated()
.and()
.cors()
.and()
.apply(new JwtConfigurer(tokenProvider));
}
}
我的类令牌提供程序:
@Service
public class JwtTokenProvider{
@Value("${security.jwt.token.secret-key:secret}")
private String secretKey = "secret";
@Value("${security.jwt.token.expire-length:3600000}")
private long validityInMilliseconds = 3600000; // 1h
@Autowired
private UserDetailsService userDetailsService;
Algorithm algorithm = null;
@PostConstruct
protected void init() {
secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes());
algorithm = Algorithm.HMAC256(secretKey.getBytes());
}
public Token createAccessToken(String email, List<String> roles) {
Date now = new Date();
Date validity = new Date(now.getTime() + validityInMilliseconds);
var accessToken = getAccessToken(email, roles, now, validity);
var refreshToken = getRefreshToken(email, roles, now);
return new Token(email, true, now, validity, accessToken, refreshToken);
}
public Token refreshToken(String refreshToken) {
if (refreshToken.contains("Bearer ")) refreshToken =
refreshToken.substring("Bearer ".length());
JWTVerifier verifier = JWT.require(algorithm).build();
DecodedJWT decodedJWT = verifier.verify(refreshToken);
String email = decodedJWT.getSubject();
List<String> roles = decodedJWT.getClaim("roles").asList(String.class);
return createAccessToken(email, roles);
}
private String getAccessToken(String email, List<String> roles, Date now, Date validity) {
String issuerUrl = ServletUriComponentsBuilder
.fromCurrentContextPath().build().toUriString();
return JWT.create()
.withClaim("roles", roles)
.withIssuedAt(now)
.withExpiresAt(validity)
.withSubject(email)
.withIssuer(issuerUrl)
.sign(algorithm)
.strip();
}
private String getRefreshToken(String email, List<String> roles, Date now) {
Date validityRefreshToken = new Date(now.getTime() + (validityInMilliseconds * 3));
return JWT.create()
.withClaim("roles", roles)
.withIssuedAt(now)
.withExpiresAt(validityRefreshToken)
.withSubject(email)
.sign(algorithm)
.strip();
}
public Authentication getAuthentication(String token) {
DecodedJWT decodedJWT = decodedToken(token);
UserDetails userDetails = this.userDetailsService
.loadUserByUsername(decodedJWT.getSubject());
return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities());
}
private DecodedJWT decodedToken(String token) {
Algorithm alg = Algorithm.HMAC256(secretKey.getBytes());
JWTVerifier verifier = JWT.require(alg).build();
DecodedJWT decodedJWT = verifier.verify(token);
return decodedJWT;
}
public String resolveToken(HttpServletRequest req) {
String bearerToken = req.getHeader("Authorization");
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring("Bearer ".length());
}
return null;
}
public boolean validateToken(String token) {
DecodedJWT decodedJWT = decodedToken(token);
try {
if (decodedJWT.getExpiresAt().before(new Date())) {
return false;
}
return true;
} catch (Exception e) {
throw new InvalidJwtAuthenticationException("Expired or invalid JWT token!");
}
}
}
我的客户端服务:
@Service
public class ClientService implements UserDetailsService {
private final ClientRepository clientRepository;
private final ModelMapper modelMapper;
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
var user = clientRepository.findByClientEmail(email);
if (user != null) {
return user;
} else {
throw new UsernameNotFoundException("Email " + email + " not found!");
}
}
}
**在调试过程中,我遇到了以下情况:**用户名密码验证令牌凭据=[PROTECTED],已验证=false,详细信息=null,授予的权限=[]]
1条答案
按热度按时间zzlelutf1#
**简短回答:**存储在数据库中的密码必须使用
PasswordEncoder
加密。**详细答案:**您创建了
PasswordEncoder
类型的Bean,因此当您调用AuthenticationManager
类的.authenticate()
方法时,AuthenticationProvider
将使用该Bean。作为stated in java docs,
DelegatingPasswordEncoder
希望您的密码以如下格式存储在DB中:{编码器ID}加密密码
您使用
pbkdf2
密码编码器作为默认编码器,因此DB中的密码应如下所示:{pbkdf 2}已加密密码
从返回的
ClientEntity
可以看出,在将该实体保存到DB时没有使用PasswordEncoder
,因此存储的是原始密码而不是加密密码。身份验证流程应如下所示:
1.您的应用注册一个用户,使用
PasswordEncoder
bean将其密码以 * 加密形式 * 存储在数据库中;1.用户通过API端点的登录表单将其用户名(电子邮件或任何必要的东西)和 * 原始 * 密码传递给您的应用程序;
AuthenticationProvider
从数据库中检索 * 加密密码 *,并将其与用户提供的 * 原始 * 密码进行比较