Я слежу за этот учебник при использовании аутентификации JWT с весенней загрузкой. Я могу войти в систему и получить доступ к API от почтальона, как показано в руководстве. Однако, когда я пытаюсь сделать то же самое в браузере по адресу localhost: 8080, я получаю ошибку 401 Unauthorized.
В учебнике используется следующий метод настройки:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.authorizeRequests().antMatchers("/api/auth/**").permitAll().anyRequest()
.authenticated().and().exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
}
Когда я удаляю authenticationEntryPoint и добавляю httpbasic, в браузере отображается диалоговое окно входа в систему при доступе к localhost: 8080.
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.authorizeRequests().antMatchers("/api/auth/**").permitAll().anyRequest()
.authenticated().and().exceptionHandling()
.and().httpBasic().and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
Но когда я пытаюсь добавить httpBasic с authenticationEntryPoint, диалоговое окно входа в систему не отображается.
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.authorizeRequests().antMatchers("/api/auth/**").permitAll().anyRequest()
.authenticated().and().exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and().httpBasic().and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
}
Обновлено
unauthorizedHandler - это реализация AuthenticationEntryPoint.
@Component
public class UnauthorizedHandler implements AuthenticationEntryPoint {
private static final Logger logger = LoggerFactory.getLogger(UnauthorizedHandler.class);
@Override
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException e)
throws IOException, ServletException {
logger.error("Unauthorized error. Message - {}", e.getMessage());
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Error -> Unauthorized");
}
}
Как я могу отобразить диалоговое окно входа в систему при использовании AuthenticationEntryPoint?
Я следую этот учебник, чтобы реализовать безопасность Spring с помощью jwt. Я обновил код в исходном вопросе, чтобы включить unauthorizedHandler.
Ваша точка аутентификации ничего не делает (просто ведет журнал). Убери это.




По умолчанию exceptionHandling включен, и он использует точку входа по умолчанию, которая является Http403ForbiddenEntryPoint, когда вы настраиваете httpBasic(), он устанавливает новую точку входа по умолчанию в exceptionHandling, которая является BasicAuthenticationEntryPoint - это все по умолчанию, когда точка входа не определена явно.
Когда вы явно определяете новую точку входа .exceptionHandling().authenticationEntryPoint(some entry point), вся конфигурация по умолчанию больше не используется и будет использоваться вместо нее some entry point.
Обратите внимание, что httpBasic все еще работает, но он должен каким-то образом сообщить вашему браузеру, что аутентификация не удалась, и сообщить браузеру, чтобы он запрашивал учетные данные для http basic, и это то, что делает BasicAuthenticationEntryPoint, установив соответствующий заголовок WWW-Authenticate: Basic realm = "User Visible Realm".
В вашем UnauthorizedHandler в commence добавьте строки String realmName = "some text"; и response.addHeader("WWW-Authenticate", "Basic realm=\"" + realmName + "\"");
PS. Я не анализировал ваш случай, просто рассказал, что не так (почему не работает должным образом) и как заставить его работать - так что это решение, возможно, не подходит с точки зрения безопасности.
Это немного старовато, но я надеюсь, что мой ответ все равно кому-то поможет.
У меня была точно такая же проблема, потому что я пытался получить диалоговое окно аутентификации для чванства, но я хотел обрабатывать неавторизованные запросы без отображения диалогового окна, поэтому я сделал следующее:
@Component
public class AuthEntryPointJwt implements AuthenticationEntryPoint {
private static final Logger logger = LoggerFactory.getLogger(AuthEntryPointJwt.class);
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException {
// Requested URL contains "swagger" since it is the only page where I wanted to display login dialog when set header to display dialog and send back the response
if (request.getRequestURL().toString().contains("swagger")) {
response.setHeader("WWW-Authenticate", "BASIC");
response.sendError(response.SC_UNAUTHORIZED);
} else {
// if not, just send unauthorized error
logger.error("Unauthorized error: {}", authException.getMessage());
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Error: Unauthorized");
}
}
}
Зачем вам нужна настраиваемая точка входа для аутентификации? Что такое
unauthorizedHandler? Покажи свой код.httpBasicуже добавляет точку входа для аутентификации, чего должно быть достаточно.