我是Spring Boot的新手。
我想知道如何在Spring Boot中进行身份验证之前验证凭证DTO?
我有这个控制器:
@PostMapping
public ResponseEntity<TokenDTO> generateTokenJwt(@Valid @RequestBody CredentialsDTO credentials, BindingResult result)
throws AuthenticationException {
TokenDTO response = new TokenDTO();
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
credentials.username, credentials.password);
Authentication authentication = authenticationManager.authenticate(authenticationToken);
SecurityContextHolder.getContext().setAuthentication(authentication);
UserDetails userDetails = userDetailsService.loadUserByUsername(credentials.username);
String token = jwtTokenUtils.getToken(userDetails);
response.token = token;
return ResponseEntity.ok(response);
}
证书DTO是:
public class CredentialsDTO {
@NotEmpty
public String username;
@NotEmpty
public String password;
}
所以,当我像这样执行POST时:
curl -i -X POST \
-H "Accept:application/json" \
-H "Content-Type:application/json" \
-d \
'{
"username": "",
"password": "123456"
}' \
'http://localhost:8080/api/login'
我想显示422错误,告知用户名属性不应为空,但是,发生的情况是首先进行身份验证,返回的错误是401.
答案 0 :(得分:1)
您可以添加HandlerInterceptor的实现。
您的preHandle(...)方法的实现应该处理错误场景,然后返回false(以阻止请求被传递给其他侦听器和处理程序)。
您可以扩展HandlerInterceptorAdapter以使生活更轻松。这看起来像这样。
@Component
public class LoginInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if(isRequestToLoginUrl(request)) {
return hasValidBody(request);
}
return true;
}
}
然后你必须在Spring MVC中注册该处理程序,添加:
@Configuration
public static class WebMvcConfig extends WebMvcConfigurerAdapter {
@Autowired
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor);
}
}
答案 1 :(得分:1)
我认为问题是Spring在到达Post方法之前处理身份验证。因此,永远不会在CredentialsDTO
我建议你创建自己的UserDetailsService。这将使您能够对身份验证进行一些验证。
示例:
@Service
@Transactional(propagation = Propagation.REQUIRED)
public class UserSecurityService implements UserDetailsService {
@Autowired
UserRepository userRepository;
public User loadUserByUsername(String email) throws UsernameNotFoundException {
if (email.isEmpty()) {
//Throw whatever exception you see fitting
throw new UsernameNotFoundException("security.userNotFound");
}
User user = userRepository.getUserByEmail(email);
return user;
}
}