Ke *_*Vin 16 java spring-boot bearer-token spring-cloud-feign
嗨,试图实现的是获取从前端提交的承载令牌在 java spring boot RESTApi 控制器中,并使用伪装客户端向另一个微服务发出另一个请求?这是我所做的
上图是我如何处理邮递员的请求,这是我的控制器代码:
@Operation(summary = "Save new")
@PostMapping("/store")
public ResponseEntity<ResponseRequest<TransDeliveryPlanning>> saveNewTransDeliveryPlanning(
@Valid @RequestBody InputRequest<TransDeliveryPlanningDto> request) {
TransDeliveryPlanning newTransDeliveryPlanning = transDeliveryPlanningService.save(request);
ResponseRequest<TransDeliveryPlanning> response = new ResponseRequest<TransDeliveryPlanning>();
if (newTransDeliveryPlanning != null) {
response.setMessage(PESAN_SIMPAN_BERHASIL);
response.setData(newTransDeliveryPlanning);
} else {
response.setMessage(PESAN_SIMPAN_GAGAL);
}
return ResponseEntity.ok(response);
}
Run Code Online (Sandbox Code Playgroud)
这是我的服务的样子:
public TransDeliveryPlanning save(InputRequest<TransDeliveryPlanningDto> request) {
Future<List<PartnerDto>> initPartners = execs.submit(getDataFromAccount(transDeliveryPlanningDtSoDtoPartnerIdsSets));
}
public Callable<List<PartnerDto>> getDataFromAccount(Set<Long> ids) {
String tokenString = "i should get the token from postman, how do i get it to here?";
List<PartnerDto> partnerDtoResponse = accountFeignClient.getData("Bearer " + tokenString, ids);
return () -> partnerDtoResponse;
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,在“tokenString”中,我放了一个我质疑的字符串,我如何从邮递员那里得到它?
sta*_*ker 13
尽管建议的答案有效,但每次将令牌传递给FeignClient
调用仍然不是最好的方法。我建议为假请求创建一个拦截器,您可以从中提取令牌RequestContextHolder
并将其直接添加到请求标头中。像这样:
@Component
public class FeignClientInterceptor implements RequestInterceptor {
private static final String AUTHORIZATION_HEADER = "Authorization";
public static String getBearerTokenHeader() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getHeader("Authorization");
}
@Override
public void apply(RequestTemplate requestTemplate) {
requestTemplate.header(AUTHORIZATION_HEADER, getBearerTokenHeader());
}
}
Run Code Online (Sandbox Code Playgroud)
这样你就可以为你的问题找到一个干净的解决方案
Fon*_*ard 13
从标头获取Bearer Token 的一种简单方法是将@RequestHeader与标头名称一起使用。
请参阅下面的代码示例
@PostMapping("/some-endpoint")
public ResponseEntity<String> someClassNmae(@RequestHeader("Authorization") String bearerToken) {
System.out.println(bearerToken); // print out bearer token
// some more code
}
Run Code Online (Sandbox Code Playgroud)
您在这里有多种选择。
例如,您可以使用请求范围的 bean,并且如您所建议的那样,使用一个MVC 拦截器。
基本上,您需要为令牌值定义一个包装器:
public class BearerTokenWrapper {
private String token;
// setters and getters
}
Run Code Online (Sandbox Code Playgroud)
然后,提供一个 MVC 的实现HandlerInterceptor
:
public class BearerTokenInterceptor extends HandlerInterceptorAdapter {
private BearerTokenWrapper tokenWrapper;
public BearerTokenInterceptor(BearerTokenWrapper tokenWrapper) {
this.tokenWrapper = tokenWrapper;
}
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
final String authorizationHeaderValue = request.getHeader("Authorization");
if (authorizationHeaderValue != null && authorizationHeaderValue.startsWith("Bearer")) {
String token = authorizationHeaderValue.substring(7, authorizationHeaderValue.length());
tokenWrapper.setToken(token);
}
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
这个拦截器应该在你的 MVC 配置中注册。例如:
@EnableWebMvc
@Configuration
public class WebConfiguration extends WebConfigurer { /* or WebMvcConfigurerAdapter for Spring 4 */
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(bearerTokenInterceptor());
}
@Bean
public BearerTokenInterceptor bearerTokenInterceptor() {
return new BearerTokenInterceptor(bearerTokenWrapper());
}
@Bean
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public BearerTokenWrapper bearerTokenWrapper() {
return new BearerTokenWrapper();
}
}
Run Code Online (Sandbox Code Playgroud)
通过此设置,您可以在Service
自动装配相应的 bean 中使用 bean:
@Autowired
private BearerTokenWrapper tokenWrapper;
//...
public TransDeliveryPlanning save(InputRequest<TransDeliveryPlanningDto> request) {
Future<List<PartnerDto>> initPartners = execs.submit(getDataFromAccount(transDeliveryPlanningDtSoDtoPartnerIdsSets));
}
public Callable<List<PartnerDto>> getDataFromAccount(Set<Long> ids) {
String tokenString = tokenWrapper.getToken();
List<PartnerDto> partnerDtoResponse = accountFeignClient.getData("Bearer " + tokenString, ids);
return () -> partnerDtoResponse;
}
Run Code Online (Sandbox Code Playgroud)
类似的解决方案已经在堆栈溢出中提供。例如,请参阅此相关问题。
除了这种基于 Spring 的方法之外,您还可以尝试类似于在this other stackoverflow question 中公开的解决方案的方法。
老实说,我从未测试过它,但您似乎可以在 Feign 客户端定义中直接提供请求标头值,在您的情况下是这样的:
@FeignClient(name="AccountFeignClient")
public interface AccountFeignClient {
@RequestMapping(method = RequestMethod.GET, value = "/data")
List<PartnerDto> getData(@RequestHeader("Authorization") String token, Set<Long> ids);
}
Run Code Online (Sandbox Code Playgroud)
当然,你也可以Controller
是其他Controller
s可以扩展的common 。这Controller
将提供从头Authorization
和提供的 HTTP 请求中获取承载令牌所需的逻辑,但在我看来,上述任何解决方案都更好。
归档时间: |
|
查看次数: |
17066 次 |
最近记录: |