Давайте защитим наш Spring REST API с помощью OAuth2 и MySQL. Мы будем хранить учетные данные пользователя в базе данных MySQL, а учетные данные клиента будут храниться в базе данных в памяти. Каждый клиент имеет свой уникальный идентификатор клиента.
Чтобы обеспечить безопасность нашего REST API, нам нужно будет сделать следующее:
-
Настройте Spring Security и базу данных.
-
Настройте сервер авторизации и сервер ресурсов.
-
Получите токен доступа и токен обновления.
-
Получить защищенный ресурс (REST API) с помощью токена доступа.
Прежде чем мы начнем, давайте рассмотрим некоторые основные концепции, связанные с Spring Security OAuth2 .
Вам также может понравиться: Spring Security Authentication .
OAuth2 Роли
Владелец ресурса
Владелец ресурса — это человек (например, конечный пользователь) в приложении, которому принадлежит служба или политика безопасности.
Ресурсный сервер
Это сервер ресурсов, на котором размещен защищенный ресурс или служба.
Клиентское приложение
Клиентское приложение — это приложение, запрашивающее доступ к ресурсам, хранящимся на сервере ресурсов. Клиентское приложение также получает авторизацию от владельца ресурса.
Сервер авторизации
Сервер авторизации — это сервер, который авторизует клиентское приложение для доступа к ресурсам владельца ресурса.
заявка
Давайте начнем защищать наши конечные точки API REST .
Во-первых, нам нужно включить Spring Security, чтобы добавить функцию безопасности в приложение. Для настройки и включения Spring Security используется @EnableWebSecurity
аннотация.
Используя @EnableGlobalMethodSecurity
, мы можем легко защитить наши методы с помощью конфигураций Java. Глобальная безопасность метод активации @PreFilter
, @PostFilter
, @PreAuthorize
, и @PostAuthorize
аннотаций , если мы хотим использовать их.
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailsServiceImpl userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().authorizeRequests().antMatchers("/oauth/token")
.permitAll().anyRequest().authenticated();
}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setPasswordEncoder( bCryptPasswordEncoder() );
provider.setUserDetailsService(userDetailsService);
return provider;
}
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider());
}
}
Примечание:
-
Здесь
WebSecurityConfigurerAdapter
используется для настройки реализации безопасности. -
Endpoint /OAuth/tpken
используется для запроса токена (доступа или обновления). -
Мы внедряем пользовательскую реализацию
UserDetailsService
для извлечения пользовательских данных из базы данных. -
Мы используем определенный
BCryptPasswordEncoder
компонент для кодирования пароля.
Теперь нам нужно настроить сервер авторизации. @EnableAuhtorizationServer
Аннотаций позволяет сервер авторизации. AuthorizationServerConfigurerAdapter
реализует AuthorizationServerConfigurer
, который предоставляет все необходимые методы для настройки сервера авторизации. Он также содержит информацию о зарегистрированных клиентах и возможном доступе к областям действия и типам предоставления.
@Configuration
@EnableAuthorizationServer
public class OAuthConfiguration extends AuthorizationServerConfigurerAdapter {
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Autowired
UserDetailsService userDetailsService;
@Override
public void configure(final AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("fooClientId").secret("secret")
.authorizedGrantTypes("password", "authorization_code", "refresh_token").scopes("read","write")
.autoApprove(true);
}
@Override
public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore()).authenticationManager(authenticationManager).accessTokenConverter(defaultAccessTokenConverter())
.userDetailsService(userDetailsService);
}
@Bean
public TokenStore tokenStore(){
return new JwtTokenStore(defaultAccessTokenConverter());
}
@Bean
public JwtAccessTokenConverter defaultAccessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("123");
return converter;
}
}
Примечания по вышеуказанной конфигурации:
-
Регистрирует клиента с идентификатором клиента ‘
fooClientId
‘ и паролем ‘secret
‘, а также ролями и областью его применения. -
Определяет авторизованные типы предоставления (пароль, код авторизации, refresh_token).
-
Определяет
JwtTokenStore
для хранения токенов.
Далее нам нужно настроить сервер ресурсов. @EnableResourceServer
Аннотаций, применяется на серверах OAuth2 ресурсов, позволяет фильтра Spring Security , который проверяет подлинность запросов , используя входящий маркер OAuth2.
Класс ResourceServerConfigurerAdapter
реализует ResourceServerConfigure
, предоставляя методы для настройки правил доступа и путей, которые защищены безопасностью OAuth2.
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
private static final String RESOURCE_ID = "resource-server-rest-api";
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**").authorizeRequests().anyRequest().authenticated();
}
}
Далее нам нужно обновить application.properties
настройку базы данных MySQL. Создайте user_management
схему в MySQL и добавьте пользовательскую таблицу для хранения учетных данных пользователя с ролями.
spring.datasource.url = jdbc:mysql://localhost:3306/user_management
spring.datasource.username = root
spring.datasource.password = root
# Hibernate ddl auto (create, create-drop, update)
spring.jpa.hibernate.ddl-auto = update
# Naming strategy
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
# Use spring.jpa.properties.* for Hibernate native properties (the prefix is
# stripped before adding them to the entity manager)
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
server.port = 8080
Тестовое приложение
Чтобы получить доступ к любой защищенной конечной точке REST API, сначала нам нужно получить токен доступа. Чтобы получить токен доступа, нам нужно добавить заголовок авторизации с учетными данными клиента и добавить тело запроса с учетными данными пользователя в почтальоне.
После получения токена доступа и обновления токена мы можем получить доступ к любым защищенным конечным точкам REST API с помощью токена доступа. Когда токен доступа истек, токен обновления используется для получения нового токена доступа.
Я приложил некоторые ответы на запросы почтальонов
# getToken
# getUser
# Добавить пользователя
Вы можете обратиться ко всему проекту на GitHub .