[SPRING] spring rest 템플릿을 사용하여 서비스에 HTTP 헤더 (JWT Token) 전파
SPRINGspring rest 템플릿을 사용하여 서비스에 HTTP 헤더 (JWT Token) 전파
나는 마이크로 서비스 아키텍처를 가지고 있는데, 둘 다 스프링 보안과 JWT 토큰으로 증권화했다.
그래서, 첫 번째 마이크로 서비스를 호출 할 때 JWT 토큰을 가져 와서 이러한 자격 증명을 사용하여 다른 서비스에 요청을 보내려합니다.
어떻게 토큰을 검색하고 다른 서비스로 다시 보낼 수 있습니까?
해결법
-
==============================
1.기본적으로 토큰은 요청의 헤더에 있어야합니다 (예 : Authorization : Bearer). 그것을 얻으려면 컨트롤러에서 @RequestHeader ()를 통해 모든 헤더 값을 검색 할 수 있습니다.
기본적으로 토큰은 요청의 헤더에 있어야합니다 (예 : 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);
이제 나머지 템플릿에 HttpEntity를 전달할 수 있습니다.
template.exchange("RestSvcUrl", HttpMethod.POST, entityReq, SomeResponse.class);
희망을 도울 수 있기를 바랍니다.
-
==============================
2.필자는 작업을 완료하여 사용자 정의 필터를 작성했습니다.
필자는 작업을 완료하여 사용자 정의 필터를 작성했습니다.
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; }
이를 염두에두고, 컨트롤러에서 Rest Templace 인터셉터로 JWT 토큰을 전달하는 ThreadLocal 변수를 가진 다른 클래스를 작성했습니다.
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; }
}
public class RestTemplateInterceptor implements ClientHttpRequestInterceptor{ @Override public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { String token = RequestContext.getContext().getToken(); request.getHeaders().add(RequestContext.REQUEST_HEADER_NAME, token); return execution.execute(request, body); } }
구성에 인터셉터 추가
@PostConstruct public void addInterceptors() { List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors(); interceptors.add(new RestTemplateInterceptor()); restTemplate.setInterceptors(interceptors); }
-
==============================
3.나는 RestTemplate에 인터셉터를 특별히 추가하는 것이 더 좋다고 생각한다.
나는 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 } }
그리고 RestTemplate에 다음과 같이 추가하십시오.
@Bean fun restTemplate(): RestTemplate { val restTemplate = RestTemplate() restTemplate.interceptors.add(RestTemplateHeaderModifierInterceptor(authenticationService)) // add interceptor to send JWT along with requests. return restTemplate }
그렇게하면 RestTemplate이 필요할 때마다 자동 와이어 링을 사용하여 가져올 수 있습니다. 다음과 같이 TokenStore에서 토큰을 가져 오려면 AuthenticationService를 여전히 구현해야합니다.
val details = SecurityContextHolder.getContext().authentication.details if (details is OAuth2AuthenticationDetails) { val token = tokenStore.readAccessToken(details.tokenValue) return token.value }
from https://stackoverflow.com/questions/46729203/propagate-http-header-jwt-token-over-services-using-spring-rest-template by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] JSON을 작성할 수 없습니다 : 무한 재귀 (StackOverflowError); 중첩 예외 봄 부팅 (0) | 2019.06.27 |
---|---|
[SPRING] @ TransactionalEvents 및 @Rollback 테스트 (0) | 2019.06.27 |
[SPRING] Autowired는 Custom Constraint validator에서 Null 값을줍니다. (0) | 2019.06.26 |
[SPRING] Spring Boot + Thymeleaf가 메시지 속성을 찾지 못함 (0) | 2019.06.25 |
[SPRING] Spring jdbctemplate과 Hibernate [duplicate]의 차이점 (0) | 2019.06.25 |