gpt4 book ai didi

java - 在进行 HTTP 调用之前使用 RestTemplate 清除 Cookie

转载 作者:行者123 更新时间:2023-12-04 16:00:18 30 4
gpt4 key购买 nike

我使用 Spring-Boot 2.0.2 RestTemplate 制作以下场景:

我是一个 Rest-Consumer(客户端),它:

  1. 首先需要登录一个Spring-Security-Check
  2. 然后进行第二次调用以获取数据。

首先,我想进行身份验证调用并手动从 SET-COOKIE 中读取 JSESSIONID Cookie,并将其设置在 header 中的第二次调用中。这是我的第一次尝试:

休息客户端:

@Service
public class RestClient {
private static final String ENDPOINT_DATA = "/data";
private static final String ENDPOINT_SECURITY_CHECK = "/j_spring_security_check";

private static final String HTTP_HEADER_KEY_SET_COOKIE = "Set-Cookie";
private static final String HTTP_HEADER_KEY_COOKIE = "Cookie";

private static final String PROPERTY_SPRING_SECURITY_USER = "j_username";
private static final String PROPERTY_SPRING_SECURITY_PASS = "j_password";

private final RestTemplate restTemplate;
private final RestConfig restConfig;

@Autowired
public RestClient(RestTemplateBuilder restTemplateBuilder, final RestConfig restConfig) {

notNull(restTemplateBuilder, "restTemplateBuilder must not be null!");
this.restTemplate = restTemplateBuilder
.additionalCustomizers(new NoRedirectionHandlingRestTemplateCostumizer())
.build();

notNull(restConfig, "openIdConfig must not be null!");
this.restConfig = restConfig;
}

public String getData() {
final String jSessionCockie = jSpringSecurityLogin();
return getAuthorizeCode(jSessionCockie);
}

private String jSpringSecurityLogin() {
// read config
final String fullLoginUri = restConfig.getUrl() + ENDPOINT_SECURITY_CHECK;
final String user = restConfig.getUser();
final String password = restConfig.getPassword();

// Build entity that is send
final HttpHeaders headers = new HttpHeaders();
final String body = PROPERTY_SPRING_SECURITY_USER + "=" + user + "&" + PROPERTY_SPRING_SECURITY_PASS + "=" + password;
final HttpEntity<String> toSend = new HttpEntity<>(body, headers);

final String jSessionIdCockie;

final ResponseEntity<String> response = restTemplate.postForEntity(fullLoginUri, toSend, String.class);

// Get String "JSESSIONID=XXXX". If there are other Cookies, propably will fail.
if (HttpStatus.FOUND.equals(response.getStatusCode()) && response.getHeaders().containsKey(HTTP_HEADER_KEY_SET_COOKIE)) {
jSessionIdCockie = response.getHeaders().get(HTTP_HEADER_KEY_SET_COOKIE).get(0);
} else {
throw new Error();
}

return jSessionIdCockie;
}

private String getAuthorizeCode(final String jSessionCockie) {
// read config
final String fullDataUri = restConfig.getUrl() + ENDPOINT_DATA;

// Build entity that is send
final HttpHeaders headers = new HttpHeaders();
headers.add(HTTP_HEADER_KEY_COOKIE, jSessionCockie);
final HttpEntity<Void> toSend = new HttpEntity<>(headers);

final ResponseEntity<String> response = restTemplate.exchange(fullDataUri, HttpMethod.GET, toSend, String.class);

if (HttpStatus.OK.equals(response.getStatusCode()) && response.hasBody()) {
return response.getBody();
} else {
return "";
}
}
}

为了完整起见,这里是构造函数中使用的 Costumizer:

class NoRedirectionHandlingRestTemplateCostumizer implements RestTemplateCustomizer {
@Override
public void customize(RestTemplate restTemplate) {
final HttpClient httpClient = HttpClientBuilder.create()
.disableRedirectHandling()
.build();
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
}
}

现在,当我使用 Wiremock 进行一些功能测试时,我在数据调用的 wiremock-reqeust 历史记录中看到以下内容:

{
...
"headers":
{
"Cookie": [
"JSESSIONID=axcvueiornxniuwherwuieoiun,asdpfoiu",
"JSESSIONID=axcvueiornxniuwherwuieoiun,asdpfoiu"
],
...
},
"cookies":
{
"JSESSIONID": [
"axcvueiornxniuwherwuieoiun,asdpfoiu",
"axcvueiornxniuwherwuieoiun,asdpfoiu"
]
}
...
}

等待 - JSESSIONID 被设置了 2 次。 Cool REST 为我处理它!

第二次尝试:我可以删除 Cookie 处理。并且有效。

但第一次和第二次尝试都有问题:在第一次调用 RestClient.getData() 之后,所有后续对登录端点的调用也设置了 JSESSIONID。我不知道 Rest-Producer 如何处理这个(Session-timeout e.c.t.)。

现在我的问题/疑问:

我想强制 RestTemplate 在进行登录调用之前忘记/清除所有 Cookie(之前的原因描述)。有可能吗?我没有发现任何有用的东西。


我现在的解决方法是禁用 RestTemplate 的 Cookie 管理,并像第一次尝试一样手动完成所有操作。可以通过 RestTemplateCustomizer 禁用 CookieManagment:

class NoRedirectionHandlingRestTemplateCostumizer implements RestTemplateCustomizer {
@Override
public void customize(RestTemplate restTemplate) {
final HttpClient httpClient = HttpClientBuilder.create()
.disableRedirectHandling()
.disableCookieManagement()
.build();
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
}
}

最佳答案

正如问题中提到的,首先我们需要通过以下方式禁用cookie管理

CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(厘米).setRetryHandler(重试处理程序).setKeepAliveStrategy(connectionKeepAliveStrategy).disableCookieManagement().evictExpiredConnections().evictIdleConnections(10, TimeUnit.MINUTES).build();

并像设置任何其他 header 一样设置“Cookie” header 。

public ResponseEntity getContent(String url, Map headers, Map cookies){HttpHeaders requestHeaders = new HttpHeaders();

    // add headers
for(String key : headers.keySet()){
requestHeaders.set(key, headers.get(key));
}

// add cookies
List<String> allCookieValues = new ArrayList<>();
for(String key : cookies.keySet()){
String value = cookies.get(key);
String cookieString = MessageFormat.format("{0}={1}", key,value);
allCookieValues.add(cookieString);
}
requestHeaders.addAll(HttpHeaders.COOKIE, allCookieValues);

HttpEntity<String> httpEntity = new HttpEntity<String>(requestHeaders);
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url);
URI uri = builder.build(true).toUri();
ResponseEntity responseEntity = null;
try {
responseEntity = restTemplate.exchange(uri, HttpMethod.GET, httpEntity, byte[].class);

…………

从响应中,如果你想阅读我们可以通过以下方式读取cookie

列表 responseCookies = responseEntity.getHeaders().get(HttpHeaders.SET_COOKIE);Map cookieNameValue = new HashMap<>();

    if(requestCookies != null){
cookieNameValue.putAll(requestCookies);
}

for(String cookie : responseCookies){
String[] cookieParts = cookie.split(";")[0].split("=");
cookieNameValue.put(cookieParts[0], cookieParts[1]);
}
return cookieNameValue;

关于java - 在进行 HTTP 调用之前使用 RestTemplate 清除 Cookie,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50679875/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com