【发布时间】:2020-04-29 07:50:38
【问题描述】:
我正在使用 feign 客户端调用其他服务。 服务 A 需要联系服务 B 并且必须通过身份验证服务进行身份验证。
如果我不使用 feign,我会先使用 resttemplate 调用身份验证服务。获取令牌,将其添加到我要发送到服务 B 的 msg 的标头中。
是否可以配置为假装一个端点,他从那里获取令牌以便自动完成?
【问题讨论】:
标签: spring jwt spring-cloud-feign feign
我正在使用 feign 客户端调用其他服务。 服务 A 需要联系服务 B 并且必须通过身份验证服务进行身份验证。
如果我不使用 feign,我会先使用 resttemplate 调用身份验证服务。获取令牌,将其添加到我要发送到服务 B 的 msg 的标头中。
是否可以配置为假装一个端点,他从那里获取令牌以便自动完成?
【问题讨论】:
标签: spring jwt spring-cloud-feign feign
考虑到您已经在身份验证服务中准备了 JWT 授权和身份验证,我可以这样举个例子:
第一个使用OpenFeign的feign客户端(spring最新的feign实现)
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
// Must give a url to NOT use load balancer (we have a gateway)
// Otherwise it will throw "did you forget load balancer?" error
@FeignClient(url = "http://localhost:<port>/", name = "UserClient")
public interface UserClient
{
@PostMapping(path = "login", consumes = "application/json")
ResponseEntity<String> login(@RequestBody String user);
@GetMapping(path = "hello")
ResponseEntity<String> sayHello();
}
然后像这样获取jwt令牌:(这段代码可以在一些mvc项目中)
String username = someuser
String password = somepassword
// I wasn't able to create a json but the below data would work with spring security
String user = "{\"username\":\"" + username + "\",\"password\":\"" + password + "\"}";
ResponseEntity<String> responseEntity = userClient.login(user);
// your token could be like "<username> - <token>" kind of structure
String token = responseEntity.getBody();
然后用openfeign做一个认证请求,这段代码可以在mvc项目什么的
// If you put the token in session
String bearer = (String) req.getSession().getAttribute("Bearer");
UserClient helloClient = Feign.builder().client(new Client.Default((SSLSocketFactory) SSLSocketFactory.getDefault(), null)).contract(new SpringMvcContract()).requestInterceptor(new RequestInterceptor()
{
@Override
public void apply(RequestTemplate template)
{
System.err.println("This is adding jwt header to resttemplate of the feign");
template.header("Authorization", "Bearer " + bearer);
}
}).decoder(new Decoder()
{
@Override
public Object decode(Response response, Type type) throws IOException, DecodeException, FeignException
{
// If you have returned responseentity, feign client must be able to understand it
return new ResponseEntity<>(response.body().toString(), HttpStatus.resolve(response.status()));
}
}).target(UserClient.class, "http://localhost:4441/hello/");
// My responsebody is a simple string but it could be anything you want, as long as you have the decoder
String response = helloClient.sayHello().getBody();
Feign 客户端无法动态设置标头,尤其是来自 jwt 令牌,因为这些令牌来自另一个请求或会话中。这就是我使用 builder 设置动态标题的原因。如果你使用BasicAuthRequestInterceptor,你可以创建一个BasicAuthRequestInterceptor的@Bean,并在里面设置一个静态的用户名和密码。
【讨论】: