Je veux à chaque fois que je fais une demande via feign client, définir un en-tête spécifique avec mon utilisateur authentifié.
Voici mon filtre à partir duquel j'obtiens l'authentification et la mets au contexte de sécurité de printemps:
@EnableEurekaClient
@SpringBootApplication
@EnableFeignClients
public class PerformanceApplication {
@Bean
public Filter requestDetailsFilter() {
return new RequestDetailsFilter();
}
public static void main(String[] args) {
SpringApplication.run(PerformanceApplication.class, args);
}
private class RequestDetailsFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
String userName = ((HttpServletRequest)servletRequest).getHeader("Z-User-Details");
String pass = ((HttpServletRequest)servletRequest).getHeader("X-User-Details");
if (pass != null)
pass = decrypt(pass);
SecurityContext secure = new SecurityContextImpl();
org.springframework.security.core.Authentication token = new UsernamePasswordAuthenticationToken(userName, pass);
secure. setAuthentication(token);
SecurityContextHolder.setContext(secure);
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
private String decrypt(String str) {
try {
Cipher dcipher = new NullCipher();
// Decode base64 to get bytes
byte[] dec = new Sun.misc.BASE64Decoder().decodeBuffer(str);
// Decrypt
byte[] utf8 = dcipher.doFinal(dec);
// Decode using utf-8
return new String(utf8, "UTF8");
} catch (javax.crypto.BadPaddingException e) {
} catch (IllegalBlockSizeException e) {
} catch (UnsupportedEncodingException e) {
} catch (Java.io.IOException e) {
}
return null;
}
}
Voici mon faux client:
@FeignClient("holiday-client")
public interface EmailClient {
@RequestMapping(value = "/api/email/send", method = RequestMethod.POST)
void sendEmail(@RequestBody Email email);
}
Et ici, j'ai un intercepteur de demande:
@Component
public class FeignRequestInterceptor implements RequestInterceptor {
private String headerValue;
public FeignRequestInterceptor() {
}
public FeignRequestInterceptor(String username, String password) {
this(username, password, ISO_8859_1);
}
public FeignRequestInterceptor(String username, String password, Charset charset) {
checkNotNull(username, "username");
checkNotNull(password, "password");
this.headerValue = "Basic " + base64encode((username + ":" + password).getBytes(charset));
}
private static String base64encode(byte[] bytes) {
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(bytes);
}
@Override
public void apply(RequestTemplate requestTemplate) {
requestTemplate.header("Authorization", headerValue);
}
}
Je ne sais pas comment configurer cet intercepteur pour mon client et comment définir l'en-tête avec le nom d'utilisateur et le mot de passe. Comment puis-je y parvenir?
Vous n'avez pas vraiment besoin de votre propre implémentation du FeignRequestInterceptor
car il y a déjà BasicAuthRequestInterceptor dans le feign.auth
package qui fait exactement la même chose.
Cela dit, vous avez déjà pratiquement tout configuré. Il ne reste plus qu'à définir le bean basicAuthRequestInterceptor
avec un nom d'utilisateur et un mot de passe spécifiques:
@Bean
public RequestInterceptor basicAuthRequestInterceptor() {
return new BasicAuthRequestInterceptor("username", "password");
}