#spring #spring-security #spring-boot #spring-boot-actuator
#spring #spring-безопасность #spring-загрузка #spring-boot-actuator
Вопрос:
Я ищу способ защитить методы с @Secured
помощью аннотации Spring Boot. Примерно для 10-15 пользователей я бы не хотел подключаться к базе данных и получать оттуда пользователей и их полномочия / роли, а скорее хранить их локально в application.yml
файле, специфичном для профиля. Есть ли в Spring Boot концепция, поддерживающая эту идею? Все, что я смог найти до сих пор, работает с базовым приводом безопасности ( 'org.springframework.boot:spring-boot-starter-security'
) и выглядит следующим образом:
security:
basic:
enabled: true
user:
name: admin
password: admin
role: EXAMPLE
Тем не менее, я все еще могу получить доступ к методу с аннотацией @RolesAllowed("READ")
, хотя я бы предположил, что администратор пользователя не должен иметь доступа к указанному методу. Моя конфигурация безопасности выглядит следующим образом:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(jsr250Enabled = true)
@Profile("secure")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.fullyAuthenticated()
.and()
.httpBasic();
http.sessionManagement()
.sessionFixation()
.newSession();
http.csrf().disable();
http.headers().frameOptions().disable();
}
}
В конечном итоге это может быть другая проблема, но, возможно, это важно для моего собственного понимания.
Мне интересно, как я мог бы указать несколько пользователей с разными паролями и разными ролями в моих application.yml
и аннотированных методах, чтобы гарантировать, что только авторизованные пользователи могут получить доступ к методам.
Комментарии:
1. вы не можете указать несколько пользователей в своей конфигурации. Для этого вам нужно будет создать что-то самостоятельно.
2. @M.Deinum спасибо, я нашел довольно простой способ добиться этого.
Ответ №1:
Это может быть достигнуто с помощью пользовательских ConfigurationProperties
:
@ConfigurationProperties("application")
public class ApplicationClients {
private final List<ApplicationClient> clients = new ArrayList<>();
public List<ApplicationClient> getClients() {
return this.clients;
}
}
@Getter
@Setter
public class ApplicationClient {
private String username;
private String password;
private String[] roles;
}
@Configuration
@EnableConfigurationProperties(ApplicationClients.class)
public class AuthenticationManagerConfig extends
GlobalAuthenticationConfigurerAdapter {
@Autowired
ApplicationClients application;
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
for (ApplicationClient client : application.getClients()) {
auth.inMemoryAuthentication()
.withUser(client.getUsername()).password(client.getPassword()).roles(client.getRoles());
}
}
}
и затем вы можете указать пользователей в своем application.yml
:
application:
clients:
- username: rw
password: rw
roles: READ,WRITE
- username: r
password: r
roles: READ
- username: w
password: w
roles: WRITE
не забудьте добавить spring-boot-configuration-processor
в свой build.gradle
:
compile 'org.springframework.boot:spring-boot-configuration-processor'
Обновление апрель 2018
Для Spring Boot 2.0 я использую следующий класс:
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
@EnableWebSecurity
@ConditionalOnWebApplication
@EnableConfigurationProperties(ApplicationClients.class)
@RequiredArgsConstructor
@Slf4j
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final ApplicationClients application;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.requestMatchers(EndpointRequest.to("health")).permitAll()
.requestMatchers(EndpointRequest.toAnyEndpoint()).hasRole("ACTUATOR")
.antMatchers("/rest/**").authenticated()
.antMatchers("/soap/**").authenticated()
.and()
.cors()
.and()
.httpBasic();
}
@Bean
public InMemoryUserDetailsManager inMemoryUserDetailsManager() {
final InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
log.info("Importing {} clients:", application.getClients().size());
application.getClients().forEach(client -> {
manager.createUser(User.withDefaultPasswordEncoder()
.username(client.getUsername())
.password(client.getPassword())
.roles(client.getRoles())
.build());
log.info("Imported client {}", client.toString());
});
return manager;
}
}
Пожалуйста, имейте в виду, что User.withDefaultPasswordEncoder()
это помечено как устаревшее из соображений безопасности.
Комментарии:
1. Спасибо за ваше решение. У меня возникли проблемы, потому что класс ApplicationClient и все значения имеют значение null. Просто добавлены установщики и получатели в ApplicationClient, как описано здесь docs.spring.io/spring-boot/docs/current/reference/html /… и теперь все работает.