Я работаю над небольшим проектом в целях обучения, который использует Spring Security, AngularJS и REST. При реализации логина столкнулся с такой проблемой:
Если ввожу неверную пару логин/пароль, то мой JsonAuthenticationFilter
кидает BadCredentialsException
. Соответственно после этого SimpleUrlAuthenticationFailureHandler
возвращает 401 http-код. Но сразу затем DispatcherServlet
посылает POST запрос по URL /login
. Соответствующего метода для обработки этого запроса у меня, конечно, нет, потому что ведь Spring Security обрабатывает все подобные ситуации, а значит в итоге я получаю 405 http-код.
Вопрос: почему DispatcherServlet
делает это, и как от этого избавиться? В случае с верными логином и паролем все хорошо - могу войти, но в случае ошибки мне нужен мой 401, чтобы работать с ним через Angular...
Логи:
Spring Security config:
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.dataart.vmishustin.service.security"/>
<http entry-point-ref="restAuthenticationEntryPoint">
<intercept-url pattern="/resources/**" access="permitAll()"/>
<intercept-url pattern="/login" access="permitAll()"/>
<intercept-url pattern="/registration" access="permitAll()"/>
<intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')"/>
<intercept-url pattern="/**" access="hasAnyRole('ROLE_ADMIN', 'ROLE_USER')"/>
<access-denied-handler error-page="/access_denied"/>
<form-login
authentication-success-handler-ref="customUrlAuthenticationSuccessHandler"
authentication-failure-handler-ref="simpleUrlAuthenticationFailureHandler"
login-page="/login"
username-parameter="username"
password-parameter="password"/>
<csrf disabled="true"/>
<remember-me remember-me-parameter="rememberMe"/>
<custom-filter ref="jsonAuthenticationFilter" before="FORM_LOGIN_FILTER"/>
</http>
<authentication-manager id="authenticationManager">
<authentication-provider user-service-ref="customUserDetailsService">
<password-encoder ref="passwordEncoder"/>
</authentication-provider>
</authentication-manager>
<beans:bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
<beans:constructor-arg name="strength" value="11"/>
</beans:bean>
<beans:bean id="jsonAuthenticationFilter" class="com.dataart.vmishustin.service.security.filters.JsonAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager"/>
<beans:property name="authenticationFailureHandler" ref="simpleUrlAuthenticationFailureHandler"/>
<beans:property name="authenticationSuccessHandler" ref="customUrlAuthenticationSuccessHandler"/>
</beans:bean>
<beans:bean id="simpleUrlAuthenticationFailureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"/>
RestAuthenticationEntryPoint
@Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
response.sendError( HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized" );
}
}
JsonAuthenticationFilter
@Component
public class JsonAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private static final Logger LOG = LoggerFactory.getLogger(JsonAuthenticationFilter.class);
private static final String JSON_CONTENT_TYPE = "application/json;charset=UTF-8";
private static final String REQUIRED_METHOD = "POST";
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (!request.getMethod().equals(REQUIRED_METHOD)) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
if (JSON_CONTENT_TYPE.equals(request.getHeader("Content-Type"))) {
LoginRequest loginRequest = this.getLoginRequest(request);
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword());
setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
} else {
return super.attemptAuthentication(request, response);
}
}
private LoginRequest getLoginRequest(HttpServletRequest request) {
LoginRequest loginRequest = null;
try (BufferedReader reader = request.getReader()) {
Gson gson = new Gson();
loginRequest = gson.fromJson(reader, LoginRequest.class);
} catch (IOException e) {
LOG.error("IOException has been thrown", e);
}
if (loginRequest == null) {
loginRequest = new LoginRequest();
}
return loginRequest;
}
}
Если потребуются еще какие-то классы или конфигурация, то я обязательно добавлю, но прямо сейчас даже представить не могу, где может быть проблема. Буду рад любой помощи. Спасибо
Оборудование для ресторана: новинки профессиональной кухонной техники
Частный дом престарелых в Киеве: комфорт, забота и профессиональный уход
Представим, что есть строки: 'Привет, у тебя есть чит?', 'Привет, у тебя есть чит', 'Привет, пойдём сегодня читать?'
Извлекаю из базы данных строки, изображение, дату помещаю значения в поля ввода изменяю и произвожу "апдейт",- работает все кроме изображения!...
Нужно открыть поток для чтения бинарного файла, но выдаёт ошибкуЯ делал десктопное приложение, а нужно на мобильное
Как лучше сделать многоязычность в приложении? На данный момент использую файлы ресурсов и там перевожу нужные мне слова на разные языки,...