В моем приложении нам нужно проверить токен аутентификации, переданный в заголовке авторизации. Оба заголовка clientName и Authorizaiton являются обязательными. Если clientName не передается, мы просто должны записать, что «имя клиента отсутствует в запросе». В конфигурации Auth мы применяем безопасность только к операциям записи. Проблема заключается в том, что если в первый раз передаются правильные clientName и токен авторизации, то следующие вызовы API работают нормально, даже если отсутствуют оба требуемых заголовка (проблема наблюдается при выполнении вызова от swagger / почтальона. Ожидаемый ответ - 403: запрещено).
Однако, когда я проверяю его, я получаю правильный запрещенный код ошибки. Когда я его отладил, обнаружил, что SecurityContextHolder.getContext()
по-прежнему возвращает последний заданный контекст.
Нужно ли также делать SecurityContextHolder.getContext().setAuthentication(null)
, когда отсутствуют заголовки?
Ниже приведен пример кода :
if (StringUtils.isEmpty(httpRequest.getHeader(clientName)) {
log.info("missing client information");
} else {
final String authorizationHeader = httpRequest.getHeader(HttpHeaders.AUTHORIZATION);
if (!StringUtils.isEmpty(clientName) && !StringUtils.isEmpty(authorizationHeader)) {
Matcher matcher = BEARER_TOKEN_PATTERN.matcher(authorizationHeader);
if (matcher.matches()) {
Client client = null;
try {
client = authService.load(clientName);
} catch (NotFoundException e) {
log.debug("Client not registered");
}
final String storedToken = !ObjectUtils.isEmpty(client) ? client.getClientSecret() : StringUtils.EMPTY;
if (storedToken.equals(matcher.group(2))) {
ClientAuthentication clientAuthentication = new ClientAuthentication(client, storedToken, client.getScopes());
SecurityContextHolder.getContext().setAuthentication(clientAuthentication);
}
}
}
}
}
chain.doFilter(request, response);
Вот AuthConfiguration:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class AuthConfiguration extends WebSecurityConfigurerAdapter {
private final Boolean isSecurityEnabled;
@Autowired
private AuthService authService;
@Autowired
public AuthConfiguration(final MyProps props) {
isSecurityEnabled = props.getIsSecurityEnabled();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(new MyCustomAuthenticationFilter(authService), BasicAuthenticationFilter.class);
if (isSecurityEnabled) {
http.requestCache()
.requestCache(new NullRequestCache())
.and().csrf().disable().formLogin().disable()
.authorizeRequests().antMatchers(HttpMethod.OPTIONS).permitAll()
.antMatchers(HttpMethod.POST, "/api/v*/channels/**")
.hasAnyAuthority(Scope.CHANNELS_WRITE.getDefaultScope(), Scope.ADMIN.getDefaultScope())
.antMatchers(HttpMethod.PUT, "/api/v*/channels/**")
.hasAnyAuthority(Scope.CHANNELS_WRITE.getDefaultScope(), Scope.ADMIN.getDefaultScope())
.antMatchers(HttpMethod.GET).permitAll()
.antMatchers(HttpMethod.PUT).authenticated()
.antMatchers(HttpMethod.DELETE).authenticated()
.antMatchers(HttpMethod.PATCH).authenticated()
.antMatchers(HttpMethod.POST).authenticated();
} else {
http.csrf().disable().formLogin().disable().authorizeRequests()
.antMatchers("/api/**").permitAll();
}
}
}```