У меня есть API, который должен быть защищен двумя различными способами:
1) Использование JWT для всех URL-адресов запроса, кроме 1, который должен быть защищен с помощью Basic Auth
2)Базовая аутентификация для одного URL.
У меня есть настройки безопасности как для JWT, так и для базовой аутентификации.Моя проблема в том, что когда я делаю запрос к URL-адресу Basic Authenticated, используя действительные имя пользователя и пароль, он успешно аутентифицирует меня и выполняет свою работу по хранению данных в cassandra.
Затем я собираюсь сгенерировать токен для ВСЕХ URL-адресов других запросов через / api / login и добавить его в заголовок Authorization: Bearer {Token}.
Однако, если бы я былаутентифицированный с помощью обычной аутентификации, я могу получить доступ к другим URL-адресам (защищенным аутентификацией JWT), даже не имея токена в запросе.
Когда я получаю доступ к защищенным JWT-URL-адресам без аутентификации с помощью базовой аутентификации, я должен отправитьтокен в шапке и он работает как положено ..
Стоит ли ожидать этого?Как я полагаю, несмотря на то, что я прошел проверку подлинности с помощью базовой аутентификации для одной конечной точки, мне все равно придется отправлять токены в запросе для всех других защищенных конечных точек JWT.
Я нашел такой ответ: множественная аутентификация SpringBootАдаптер
, а также эту статью: https://docs.spring.io/spring-security/site/docs/4.2.x/reference/htmlsingle/#multiple-httpsecurity
и попытался реализовать решения, но проблема, как объяснено, все еще возникает.
Класс конфигурации безопасности имеет видследует:
@Configuration
@EnableWebSecurity
public class SecurityHttpConfig extends WebSecurityConfigurerAdapter {
@Configuration
@Order(1)
public static class BasicAuthSecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${basic.auth.user}")
private String basicAuthUsername;
@Value("${basic.auth.password}")
private String basicAuthPassword;
@Value("${crashboxx.consume.endpoint}")
private String crashBoxxConsumeEndpoint;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().antMatchers("/v1/crash/consumeCrashBoxxEvent").hasRole("ADMIN").and()
.httpBasic().authenticationEntryPoint(getBasicAuthEntryPoint()).and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);// We don't need sessions to be created.
}
@Bean
public CustomBasicAuthenticationEntryPoint getBasicAuthEntryPoint() {
return new CustomBasicAuthenticationEntryPoint();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
auth.inMemoryAuthentication().withUser(basicAuthUsername).password(encoder.encode(basicAuthPassword))
.roles("ADMIN");
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
@Configuration
@Order(2)
public static class JwtWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
@Autowired
private JwtAuthenticationProvider jwtAuthenticationProvider;
// Any endpoints that require no authorization should be added here..
@Value("${api.login.endpoint}")
private String loginEndpoint;
@Autowired
public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) {
authenticationManagerBuilder.authenticationProvider(jwtAuthenticationProvider);
}
@Bean
public JwtAuthenticationTokenFilter authenticationTokenFilterBean() {
return new JwtAuthenticationTokenFilter();
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable().exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests().antMatchers("/api/login").permitAll().anyRequest().authenticated();
httpSecurity.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
httpSecurity.headers().cacheControl();
}
}
С классом BasicAuthEntryPoint:
public class CustomBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint {
private static final Gson gson = new Gson();
@Override
public void commence(final HttpServletRequest request, final HttpServletResponse response,
final AuthenticationException authException) throws IOException, ServletException {
// Authentication failed, send error response.
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
PrintWriter writer = response.getWriter();
writer.println(gson.toJson("HTTP Status 401 : " + authException.getMessage()));
}
@Override
public void afterPropertiesSet() throws Exception {
setRealmName("Realm");
super.afterPropertiesSet();
}
Также JWT impl:
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
@Value("${jwt.header}")
private String tokenHeader;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
final String requestHeader = request.getHeader(tokenHeader);
// Ensure Auth Header contains 'Bearer'
if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
String authToken = requestHeader.substring(7);
JwtAuthentication authentication = new JwtAuthentication(authToken);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
chain.doFilter(request, response);
}
Я надеюсь, что это имеет смысл .. Если естьеще вопросы, пожалуйста, дайте мне знать, но, кажется, не могу обойти этот вопрос.
Сначала я добавил «особый случай», который является URL-адресом для базовой аутентификации, но все равно не имеет никаких различий.
Спасибо