Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用SpringREST模板在服务上传播HTTP头(JWT令牌)_Java_Spring_Rest_Jwt - Fatal编程技术网

Java 使用SpringREST模板在服务上传播HTTP头(JWT令牌)

Java 使用SpringREST模板在服务上传播HTTP头(JWT令牌),java,spring,rest,jwt,Java,Spring,Rest,Jwt,我有一个微服务架构,它们都由spring security和JWT令牌进行了安全保护 因此,当我调用我的第一个微服务时,我希望使用JWT令牌并使用这些凭据向另一个服务发送请求 如何检索令牌并再次发送到其他服务?基本上,您的令牌应该位于请求的标头中,例如:Authorization:Bearer。要获取它,您可以通过控制器中的@RequestHeader()检索任何头值: @GetMapping("/someMapping") public String someMethod(@RequestHe

我有一个微服务架构,它们都由spring security和JWT令牌进行了安全保护

因此,当我调用我的第一个微服务时,我希望使用JWT令牌并使用这些凭据向另一个服务发送请求


如何检索令牌并再次发送到其他服务?

基本上,您的令牌应该位于请求的标头中,例如:Authorization:Bearer。要获取它,您可以通过控制器中的@RequestHeader()检索任何头值:

@GetMapping("/someMapping")
public String someMethod(@RequestHeader("Authorization") String token) {

}
现在,您可以将令牌放置在以下请求的标头中:

HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", token);

HttpEntity<RestRequest> entityReq = new HttpEntity<RestRequest>(request, headers);

希望我能帮忙

我已经完成了任务,创建了一个自定义过滤器

public class RequestFilter implements Filter{



    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String token = httpServletRequest.getHeader(RequestContext.REQUEST_HEADER_NAME);

        if (token == null || "".equals(token)) {
            throw new IllegalArgumentException("Can't retrieve JWT Token");
        }

        RequestContext.getContext().setToken(token);
        chain.doFilter(request, response);

    }

    @Override
    public void destroy() { }

    @Override
    public void init(FilterConfig arg0) throws ServletException {}


}
然后,在我的配置中设置

    @Bean
public FilterRegistrationBean getPeticionFilter() {

    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(new RequestFilter());
    registration.addUrlPatterns("/*");
    registration.setName("requestFilter");

    return registration;
}
考虑到这一点,我创建了另一个带有ThreadLocal变量的类,以将JWT令牌从控制器传递到Rest Templace拦截器

public class RequestContext {

public static final String REQUEST_HEADER_NAME = "Authorization";

private static final ThreadLocal<RequestContext> CONTEXT = new ThreadLocal<>();

private String token;

public static RequestContext getContext() {
    RequestContext result = CONTEXT.get();

    if (result == null) {
        result = new RequestContext();
        CONTEXT.set(result);
    }

    return result;
}

public String getToken() {
    return token;
}

public void setToken(String token) {
    this.token = token;
}
将拦截器添加到配置中

  @PostConstruct
public void addInterceptors() {
    List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();
    interceptors.add(new RestTemplateInterceptor());
    restTemplate.setInterceptors(interceptors);
}
@PostConstruct
公共无效附加接收器(){
List interceptors=restemplate.getInterceptors();
add(新的restemplateinterceptor());
restTemplate.setInterceptors(拦截器);
}

我认为最好将拦截器专门添加到RestTemplate中,如下所示:

class RestTemplateHeaderModifierInterceptor(private val authenticationService: IAuthenticationService) : ClientHttpRequestInterceptor {
    override fun intercept(request: org.springframework.http.HttpRequest, body: ByteArray, execution: ClientHttpRequestExecution): ClientHttpResponse {
        if (!request.headers.containsKey("Authorization")) {
            // don't overwrite, just add if not there.
            val jwt = authenticationService.getCurrentUser()!!.jwt
            request.headers.add("Authorization", "Bearer $jwt")
        }
        val response = execution.execute(request, body)
        return response
    }
}

val details = SecurityContextHolder.getContext().authentication.details
if (details is OAuth2AuthenticationDetails) {
   val token = tokenStore.readAccessToken(details.tokenValue)
   return token.value
}

并将其添加到RestTemplate,如下所示:

@Bean
fun restTemplate(): RestTemplate {
    val restTemplate = RestTemplate()
restTemplate.interceptors.add(RestTemplateHeaderModifierInterceptor(authenticationService)) // add interceptor to send JWT along with requests.
    return restTemplate
}
这样,每次需要RestTemplate时,您都可以使用autowiring来获取它。您仍然需要实现AuthenticationService才能从TokenStore获取令牌,如下所示:

class RestTemplateHeaderModifierInterceptor(private val authenticationService: IAuthenticationService) : ClientHttpRequestInterceptor {
    override fun intercept(request: org.springframework.http.HttpRequest, body: ByteArray, execution: ClientHttpRequestExecution): ClientHttpResponse {
        if (!request.headers.containsKey("Authorization")) {
            // don't overwrite, just add if not there.
            val jwt = authenticationService.getCurrentUser()!!.jwt
            request.headers.add("Authorization", "Bearer $jwt")
        }
        val response = execution.execute(request, body)
        return response
    }
}

val details = SecurityContextHolder.getContext().authentication.details
if (details is OAuth2AuthenticationDetails) {
   val token = tokenStore.readAccessToken(details.tokenValue)
   return token.value
}


如果有一些代码示例,那就太棒了:)没错。和你处理任何头球的方法一样。看起来是很好的解决方案,但有点“手工”。我希望使用一种不同的解决方案,使用ClientHttpRequestInterceptor这样的拦截器。但我不知道如何从那里取回代币。例如,具有TraceInterceptorConfiguration的sleuth库也在执行相同的操作。不需要手动添加标题,或者您可以使用控制器建议(类级别注释)而不是拦截器。在那里你也有可能注入headersHi人,我得到同样的问题,你可以显示所有的代码。我的resftul api工作正常,但客户端有问题。@dragonalvaro您使用了哪个RequestContext?这看起来很危险,因为从未调用
CONTEXT.remove()
。Web服务器通常使用线程池,如果您将一个值设置为threadlocal而不删除它,它将在其他请求中可用。注意:
request.headers.add(“授权”,“持有人$jwt”)
可以从Spring 5.1起被
request.headers.setBearerAuth(jwt)
替换