как совместить httpbasic и formlogin в spring security?
В spring boot приложении есть api часть и интерфейс на vaadin. Хочу для api настроить http basic, а для интерфейса formlogin. в данном варианте работает только http basic, а formlogin не принимает логин-пароль
protected void configure(HttpSecurity http) throws Exception {
http.requestCache()
.requestCache(new CustomRequestCache())
.and().authorizeRequests()
.antMatchers("/v2/api-docs",
"/configuration/ui",
"/swagger-resources/**",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**",
"/configuration/**",
"/swagger*/**",
"/console/**").permitAll()
.requestMatchers(SecurityUtils::isFrameworkInternalRequest).permitAll()
.antMatchers(HttpMethod.GET).hasAnyRole(COMMITTEE_MEMBER,BUSINESS_ADMINISTRATOR)
.antMatchers(HttpMethod.DELETE).denyAll()
.antMatchers(HttpMethod.HEAD).denyAll()
.antMatchers(HttpMethod.OPTIONS).denyAll()
.antMatchers(HttpMethod.PATCH).denyAll()
.antMatchers(HttpMethod.POST).denyAll()
.antMatchers(HttpMethod.PUT).denyAll()
.antMatchers(HttpMethod.TRACE).denyAll()
.anyRequest().authenticated().and()
.httpBasic().and()
.csrf().disable()
.addFilter(new AuthorizationFilter(authenticationManager(), userRepository))
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().formLogin()
.loginPage(LOGIN_URL).permitAll()
.loginProcessingUrl(LOGIN_PROCESSING_URL)
.failureUrl(LOGIN_FAILURE_URL)
.and().logout().logoutSuccessUrl(LOGOUT_SUCCESS_URL);
}
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user")
.password(passwordEncoder().encode("******"))
.roles(ADMINISTRATOR);
}
public UserDetailsService userDetailsService() {
UserDetails user =
User.withUsername("admin")
.password("{noop}*******")
.roles(ADMINISTRATOR)
.build();
return new InMemoryUserDetailsManager(user);
}
Как настроить их на совместную деятельность?
Ответы (1 шт):
Автор решения: tequillaz
→ Ссылка
Доступ к разным компонентам системы с разными параметрами безопасности настраивается путем создания нескольких бинов - наследников WebSecurityConfigurerAdapter. В примере ниже создается 2 конфигурации: 1-ая - с доступом в систему пользователей из БД с jwt-токеном, 2-ая - публичный доступ без авторизации.
Конфигурация 1
@Order(102)
@Configuration
public class PrivateConfig extends WebSecurityConfigurerAdapter {
private final JwtTokenProvider jwtTokenProvider;
private final UserDetailsService userDetailsService;
private final PasswordEncoder passwordEncoder;
@Autowired
public PrivateConfig(
JwtTokenProvider jwtTokenProvider,
@Qualifier("userDetailsServiceImpl") UserDetailsService userDetailsService,
PasswordEncoder passwordEncoder) {
this.jwtTokenProvider = jwtTokenProvider;
this.userDetailsService = userDetailsService;
this.passwordEncoder = passwordEncoder;
}
@Primary
@Override
@Bean(name = "authenticationManagerBeanGENERIC")
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// Выключить простую аутентификацию
http.httpBasic().disable();
// CSRF & CORS
http.csrf().disable();
http.cors();
// Взаимодействие без сохранения состояния
// Сессию создавать не надо
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// Правила проверки
http.antMatcher("/api/**")
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/api/profiles/forms").hasAuthority("ADMIN")
.antMatchers(HttpMethod.DELETE, "/api/profiles/*").hasAuthority("ADMIN")
.antMatchers(HttpMethod.GET, "/api/account/me").hasAnyAuthority("ADMIN", "USER")
.antMatchers(HttpMethod.GET, "/api/account/logout").hasAnyAuthority("ADMIN", "USER")
.antMatchers("/api/**").hasAuthority("USER"); // Доступ к REST API только для пользователей
// Фильтря для JWT-аутентификации
JwtTokenFilter filter = new JwtTokenFilter(jwtTokenProvider);
http.addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder);
}
}
Конфигурация 2
@Order(100)
@Configuration
@EnableWebSecurity
public class PublicConfig extends WebSecurityConfigurerAdapter {
private static final String[] ANT_PATTERNS = {
"/api/public/**",
"/api/dictionaries/**",
"/api/registration/**",
"/api/account/login",
"/api/account/password/reset/**",
"/api/account/confirm",
"/api/search/egrul",
"/api/search/credentials"
};
@Override
protected void configure(HttpSecurity http) throws Exception {
// Выключить простую аутентификацию
http.httpBasic().disable();
// CSRF & CORS
http.csrf().disable();
http.cors();
// Взаимодействие без сохранения состояния
// Сессию создавать не надо
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// Правила проверки
http.requestMatchers(requestMatcherConfigurer -> requestMatcherConfigurer.antMatchers(ANT_PATTERNS))
.authorizeRequests()
.anyRequest()
.permitAll();
}
}
При этом нужно понимать:
- Конфигурации должны быть разграничены по области применения путем указания для каких компонентов системы они должны срабатывать. В примере выше это реализуется через
http.antMatcher(...)иhttp.requestMathcers(...). - Необходимо явно указать приоритет проверки конфигурации. Хорошим практикой считается назначение приоритета в зависимости от размера области действия: чем большую область действия (больше компонент) охватывает конфигурация, тем позднее она должна отрабать и тем большее значение приоритета необходимо указать. В примере выше проверки по
PublicConfigвыполняются раньше, чемPrivateConfig