Java Apache HttpClient-身份验证失效

问题描述

我希望这个问题对每个人都有意义,所以这里继续。我有一个Singleton HttpClient管理器类,该类在实例化后将针对Windows Live(Microsoft Auth)进行身份验证

但是,在一段时间不活动(缺少请求)后,此身份验证变得过时,随后对URL的请求返回了一个页面,要求我登录。我的问题本质上是,我应该如何处理对服务器的重新身份验证?我是否应该有另一个线程定期发出get请求并检查是否返回了登录页面,然后重新实例化HttpClient?请让我知道有什么最佳实践。

这是我的连接管理器类中执行身份验证的摘录:

    public static synchronized httpconnectionManager getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new httpconnectionManager();
        }
        return INSTANCE;
    }

    private httpconnectionManager() {
        final PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        connectionManager.setMaxTotal(100);
        connectionManager.setDefaultMaxPerRoute(40);

        client = HttpClients.custom()
                .setDefaultRequestConfig(RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build())
                .setConnectionManager(connectionManager)
                .disableRedirectHandling()
                .build();

        try {
            // Prepare HTTPClient by performing Authentication Handshake
            performAuthenticationHandshake();
        } catch (IOException ioException) {
            connectionLogger.log(Level.ERROR,"Unable to Authenticate to https://login.live.com");
        } catch (HttpException httpException) {
            connectionLogger.log(Level.ERROR,httpException.getMessage());
        }
    }

    private void performAuthenticationHandshake() throws IOException,HttpException {
        final HttpGet authenticatedGet = new HttpGet(LIVE_URI);
        final HttpResponse authGetResponse = client.execute(authenticatedGet);

        final String authResponseStr = IoUtils.toString(authGetResponse.getEntity().getContent(),StandardCharsets.UTF_8);

        final HttpPost credentialsPost = getCredentialsPost(authResponseStr);
        final HttpResponse credentialsPostResponse = client.execute(credentialsPost);

        if (credentialsPostResponse.getStatusLine().getStatusCode() != 302) {
            throw new HttpException("An invalid status code was returned in credentialsPostResponse (Updated TOS?)): " + credentialsPostResponse.getStatusLine().getStatusCode());
        }

        final String locationURIStr = Arrays.stream(credentialsPostResponse.getAllHeaders())
                .filter(header -> header.getName().startsWith("Location"))
                .map(Header::getValue)
                .findFirst()
                .orElseThrow(HttpException::new);

        final HttpGet locationGet = new HttpGet(locationURIStr);
        final HttpResponse locationGetResponse = client.execute(locationGet);

        if (locationGetResponse.getStatusLine().getStatusCode() != 302) {
            throw new HttpException("An invalid status code was returned in locationGetResponse: " + locationGetResponse.getStatusLine().getStatusCode());
        }

        storeCookies(locationGetResponse.getAllHeaders());
        auth = cookieStore.stream()
                .filter(cookie -> cookie.getName().startsWith("Auth"))
                .map(NameValuePair::getValue)
                .findFirst()
                .orElseThrow(HttpException::new);

    }

解决方法

一种方法是在httpClient中使用cookiestore,并且可以从该cookiestore中获取cookie的到期日期。

我们可以像这样将cookiestore分配给httpclient。

BasicCookieStore cookieStore = new BasicCookieStore();
client = HttpClients.custom().setDefaultRequestConfig(RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build())
                .setConnectionManager(connectionManager)
                .setDefaultCookieStore(cookieStore)
                .disableRedirectHandling()
                .build();

现在,cookiestore对象包含所有cookie及其过期日期。每当您尝试在HTTPClient中执行任何URL时,我们都会检查身份验证cookie的到期日期。如果当前日期超过了身份验证cookie的过期日期,则HTTPClient必须重新登录以获取身份验证cookie并继续实际过程。

只要使用HTTPClient执行任何URL,都必须插入以下检查。

// let cookiestore one the one used in httpClient
Cookie auth = cookieStore.getCookies().stream()
            .filter(cookie -> cookie.getName().startsWith("Auth"))
            .findFirst()
            .orElseThrow(HttpException::new);

Date currentDate = new Date();
if( auth.isExpire(currentDate) ){
    performAuthenticationHandshake();
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...