Я реализую страницу входа в систему, используя Angular 7 и Spring Boot, и я получаю обработанную ошибку при входе в систему. По сути, я хочу на определенное время заблокировать вход в систему после неудачной попытки входа в систему.
Настройка HttpSecurity
@Override
protected void configure(HttpSecurity http) throws Exception {
logger.info("#### Configuring Security ###");
JWTAuthenticationFilter jwtAuthenticationFilter = new JWTAuthenticationFilter(authenticationManager());
jwtAuthenticationFilter.setFilterProcessesUrl("/rest/users/authenticate");//this override the default relative url for login: /login
http
.httpBasic().disable()
.csrf().disable()
.authorizeRequests()
.antMatchers("/rest/", "/rest/helloworld/**").permitAll()
.anyRequest().authenticated()
.and().exceptionHandling().authenticationEntryPoint(new JwtAuthenticationEntryPoint()).and()
.addFilter(jwtAuthenticationFilter);
Для обработки логина я создал фильтр
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private static Logger logger = Logger.getLogger(JWTAuthenticationFilter.class);
private AuthenticationManager authenticationManager;
public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
try {
UserDto credentials = new ObjectMapper().readValue((request.getInputStream()), UserDto.class);
return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
credentials.getUserName(),
credentials.getPassword(),
new ArrayList<>())
);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
//sucessfull authentication stuff
}
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
logger.info("Authentication failed");
ErrorMessage errorMessage = new ErrorMessage("access_denied", "Wrong email or password.");
String jsonObject = JSONUtil.toJson(errorMessage);
//processing authentication failed attempt
UserDto credentials = new ObjectMapper().readValue((request.getInputStream()), UserDto.class);
AuthenticationService authenticationService = Application.getApplicationContext().getBean(AuthenticationService.class);
int numFailedAttemptLogin = authenticationService.authenticationFailedAttempt(credentials.getUserName());
response.setStatus(403);
PrintWriter out = response.getWriter();
out.print(jsonObject);
out.flush();
out.close();
//super.unsuccessfulAuthentication(request, response, failed);
}
}
Логин работает нормально, без проблем. Моя проблема связана с методом unsuccessfulAuthentication . Когда пользователь вводит неверные учетные данные, возникает исключение BadCredentials, и вызывается метод unsuccessfulAuthentication . Здесь мне нужно снова получить доступ к форме запроса, чтобы извлечь имя пользователя и обработать неудачная попытка аутентификации , и я получаю следующее исключение
java.io.IOException: Stream closed
Это потому, что внутри метода tryAuthentication входной поток запроса читается и, очевидно, закрывается.
Как я могу получить доступ к информации тела запроса в unsuccessfulAuthentication ?
Я пытался использовать SecurityContextHolder.getContext (). GetAuthentication (), но из-за сбоя аутентификации он пуст.
У кого-нибудь есть идеи?
С наилучшими пожеланиями