Я сделал это, работая после этого блога .Но я бы хотел услышать других решений, особенно с использованием какой-либо пружинной конфигурации .Spring - очень зрелая структура, она должна (должна) иметь что-то для решения этой распространенной проблемы.
Так как HttpServletRequest
не имеет никакого метода для добавления новых заголовков, мне нужно создать собственный класс, который может добавлять новые заголовки к запросу, этого можно достичь с помощью HttpServletRequestWrapper
.Вот реализация.
public final class MutableHttpServletRequest extends HttpServletRequestWrapper {
// holds custom header and value mapping
private final Map<String, String> customHeaders;
public MutableHttpServletRequest(HttpServletRequest request) {
super(request);
this.customHeaders = new HashMap<String, String>();
}
public void putHeader(String name, String value) {
this.customHeaders.put(name, value);
}
public String getHeader(String name) {
// check the custom headers first
String headerValue = customHeaders.get(name);
if (headerValue != null) {
return headerValue;
}
// else return from into the original wrapped object
return ((HttpServletRequest) getRequest()).getHeader(name);
}
public Enumeration<String> getHeaderNames() {
// create a set of the custom header names
Set<String> set = new HashSet<String>(customHeaders.keySet());
// now add the headers from the wrapped request object
Enumeration<String> e = ((HttpServletRequest) getRequest()).getHeaderNames();
while (e.hasMoreElements()) {
// add the names of the request headers into the list
String n = e.nextElement();
set.add(n);
}
// create an enumeration from the set and return
return Collections.enumeration(set);
}
}
Фильтр, который проверяет наличие cookie до Spring-secuirty:
public class CheckAuthCookieFilter implements Filter {
private Logger logger = LoggerFactory.getLogger(getClass());
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
MutableHttpServletRequest mutableRequest = new MutableHttpServletRequest(httpServletRequest);
Cookie[] cookies = httpServletRequest.getCookies();
if (cookies != null && cookies.length > 0) {
for (Cookie cookie : cookies) {
logger.debug(cookie.getName() + " : " + cookie.getValue());
if (cookie.getName().equalsIgnoreCase("auth")) {
mutableRequest.putHeader("Authorization", URLDecoder.decode(cookie.getValue(), "utf-8"));
}
}
}
chain.doFilter(mutableRequest, response);
}
}
и, наконец, конфигурация безопасности:
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {// @formatter:off
httpSecurity
.cors()
.and().authorizeRequests()
.antMatchers("/signup/**").permitAll()
.anyRequest().authenticated()
.and().httpBasic()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().csrf().disable()
;
httpSecurity.addFilterBefore(new CheckAuthCookieFilter(), BasicAuthenticationFilter.class);
}
Мой настраиваемый фильтр будет работать до BasicAuthenticationFilter
Spring. Если присутствует файл cookie с именем auth
(который приложение создало при успешном входе в систему), то это файл cookie, который содержит базовые учетные данные аутентификации.Из этого извлекаются учетные данные и добавляются в заголовок request
.Затем BasicAuthenticationFilter
будет работать и искать Authorization
и продолжить его нормальный поток.