Как защитить REST API с помощью Spring Boot и Spring Security?
Я знаю, что защита REST API широко комментируется, но я не могу создать небольшой прототип, который соответствует моим критериям (и мне нужно подтвердить, что эти критерии реалистичны). Есть так много вариантов, как обеспечить ресурсы и как работать с Spring security, мне нужно уточнить, реалистичны ли мои потребности.
мои требования
- Аутентификатор на основе токенов-пользователи предоставят свои учетные данные и получат уникальные и ограниченные по времени маркер доступа. Я хотел бы управлять созданием токенов, проверкой действительности, истечением срока действия в моей собственной реализации.
- некоторые ресурсы REST будут общедоступными - нет необходимости аутентифицироваться вообще,
- некоторые ресурсы будут доступны только для пользователей с правами администратора,
- другой ресурс будет доступен после авторизации для всех пользователей.
- я не хочу использовать базовую аутентификацию
- конфигурация кода Java (не В XML)
текущее состояние
мой REST API работает очень хорошо, но теперь мне нужно его защитить. Когда я искал решение, я создал javax.servlet.Filter
фильтр:
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
String accessToken = request.getHeader(AUTHORIZATION_TOKEN);
Account account = accountDao.find(accessToken);
if (account == null) {
throw new UnauthorizedException();
}
chain.doFilter(req, res);
}
но это решение с javax.servlet.filters
не работает, как мне нужно, потому что есть проблема с обработкой исключений через @ControllerAdvice
С весны servlet dispatcher
.
что мне нужно
Я хотел бы знать, являются ли эти критерии реалистичными и получить какие-либо справка, как начать защиту REST API с Spring Security. Я прочитал много учебников (например, Spring Data REST + Spring Security), но все работы в очень простой конфигурации - пользователи с учетные данные хранятся в в конфигурации и мне нужно работать с СУБД и создавать собственный Аутентификатор.
пожалуйста, дайте мне некоторые идеи, как начать.
4 ответов
аутентификация на основе токенов-пользователи предоставят свои учетные данные и получат уникальный и ограниченный по времени маркер доступа. Я хотел бы управлять token создание, проверка действительности, истечение срока действия в моей собственной реализации.
На самом деле, используйте фильтр для токена Auth - лучший способ в этом случае
в конце концов, вы можете создать CRUD через данные Spring для управления свойствами токена, как истекает, и т.д.
вот мой жетон фильтр: http://pastebin.com/13WWpLq2
И Реализация Сервиса Токенов
некоторые ресурсы REST будут общедоступными - нет необходимости аутентифицироваться вообще
это не проблема, вы можете управлять своими ресурсами через spring security config следующим образом:.antMatchers("/rest/blabla/**").permitAll()
некоторые ресурсы будут доступны только для пользователей с правами администратора права,
посмотри @Secured
аннотация к класс. Пример:
@Controller
@RequestMapping(value = "/adminservice")
@Secured("ROLE_ADMIN")
public class AdminServiceController {
другой ресурс будет доступен после авторизации для всех пользователей.
назад к Spring Security configure, вы можете настроить свой url следующим образом:
http
.authorizeRequests()
.antMatchers("/openforall/**").permitAll()
.antMatchers("/alsoopen/**").permitAll()
.anyRequest().authenticated()
Я не хочу использовать базовую аутентификацию
да, через фильтр токенов ваши пользователи будут аутентифицированы.
Java конфигурация кода (не XML)
вернемся к словам выше, посмотрите на @EnableWebSecurity
.
Ваш класс будет:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {}
вы должны переопределить настроить метод. Код ниже, например, как настроить сопоставители. Это из другого проекта.
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/assets/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.usernameParameter("j_username")
.passwordParameter("j_password")
.loginPage("/login")
.defaultSuccessUrl("/", true)
.successHandler(customAuthenticationSuccessHandler)
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.invalidateHttpSession(true)
.logoutSuccessUrl("/")
.deleteCookies("JSESSIONID")
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.and()
.csrf();
}
Spring security также очень полезно для обеспечения аутентификации и авторизации для остальных URL-адресов. Нам не нужно указывать какие-либо пользовательские реализации.
во-первых, вам нужно указать точку входа-ref для restAuthenticationEntryPoint в вашей конфигурации безопасности, как показано ниже.
<security:http pattern="/api/**" entry-point-ref="restAuthenticationEntryPoint" use-expressions="true" auto-config="true" create-session="stateless" >
<security:intercept-url pattern="/api/userList" access="hasRole('ROLE_USER')"/>
<security:intercept-url pattern="/api/managerList" access="hasRole('ROLE_ADMIN')"/>
<security:custom-filter ref="preAuthFilter" position="PRE_AUTH_FILTER"/>
</security:http>
реализация для restAuthenticationEntryPoint может быть, как показано ниже.
@Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException ) throws IOException {
response.sendError( HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized" );
}
}
после этого вам нужно указать RequestHeaderAuthenticationFilter. Он содержит ключ RequestHeader. Это в основном используется для идентификации аутентификации пользователя. Обычно RequestHeader несет эту информацию при выполнении остальных вызовов. Например, рассмотрим ниже код
<bean id="preAuthFilter" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
<property name="principalRequestHeader" value="Authorization"/>
<property name="authenticationManager" ref="authenticationManager" />
</bean>
здесь
<property name="principalRequestHeader" value="Authorization"/>
"авторизация" - это ключ, представленный входящим запросом. Он содержит необходимую информацию аутентификации пользователя. Также вам нужно настроить PreAuthenticatedAuthenticationProvider для выполнения наших требование.
<bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
<property name="preAuthenticatedUserDetailsService">
<bean id="userDetailsServiceWrapper"
class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<property name="userDetailsService" ref="authenticationService"/>
</bean>
</property>
</bean>
этот код будет работать для защиты остальных URL-адресов с помощью аутентификации и авторизации без каких-либо пользовательских реализаций.
для полного кода, пожалуйста, найдите ссылку ниже:
Я тоже долго искал.Я работаю над подобным проектом.Я узнал, что у Spring есть модуль для реализации сеанса через redis. Это выглядит легко и полезно. Я тоже добавлю в свой проект. Может быть полезно:
http://docs.spring.io/spring-session/docs/1.2.1.BUILD-SNAPSHOT/reference/html5/guides/rest.html
для проверки REST API есть 2 способа
1-базовая аутентификация с использованием имени пользователя и пароля по умолчанию, установленных в приложении.свойства файла
2 - аутентификация с помощью базы данных (userDetailsService) с фактическим именем пользователя и паролем