Apache HttpClient 模拟 SSO 登陆丢失 cookie 问题解决

背景

需要用 Java 访问一个被 SSO 保护的特殊接口获取信息。

方案设计

假如我们用浏览器来实现这个功能,步骤简单如下:

  1. 输入目标 API 地址
  2. (浏览器自动重定向到 SSO 登陆页面)
  3. 输入用户名密码登陆
  4. (浏览器重定向回到 API 地址,并附带认证信息
  5. 获取目标 API 的资源信息

其中需要用户操作的是步骤 1 和步骤 3。

但要求是用 Java 来实现上述功能,关键点在于如何获取认证信息。有了认证信息,我们便能直接 call 目标 API
所以我们需要模拟浏览器的登陆行为,此时的初步想法是 [HttpClient (v4.5)](https://hc.apache.org/httpcomponents-client-4.5.x/quickstart.html) + CookieStoreHttpClient 来发送 Http 请求,CookieStore 来缓存 Cookie 信息,相当于保存上下文(context)。

方案实施与问题描述

模拟浏览器登陆实现起来稍显复杂:

  1. 创建 CookieStore,并添加到 HttpClient 来保存上下文信息。
  2. HttpClient 访问目标 API,因为需要 SSO 登陆,所以得到的 response 是一个 html 页面,即登陆页面。
  3. 解析步骤 2 中返回的登陆页面,得到登陆表单提交的地址。
  4. 构建登陆请求,填入用户名密码信息,并用 HttpClient 提交登陆请求。
  5. 获取步骤 4 的 response。此时认证信息已经被添加到 CookieStore 中,HttpClient 可以直接访问目标 API

简化后的代码如下:

// 1. 创建 CookieStore 以及 HttpClient
CookieStore cookieStore = new BasicCookieStore();
HttpClient httpClient = HttpClientBuilder.create()
        .setRedirectStrategy(new LaxRedirectStrategy()) // follow redirect,即当遇到 302 时直接处理跳转
        .setDefaultCookieStore(cookieStore)
        .build();

// 2. 获取登陆表单 url
HttpResponse response = httpClient.execute(new HttpGet("{apiPath}"));
String result = EntityUtils.toString(response.getEntity());
Pattern pattern = Pattern.compile("<form id=\"login-form\" method=\"post\" name=\"login-form\" action=\"(.+?)\">"); // 表单正则
Matcher matcher = pattern.matcher(result);
if (!matcher.find()) {
   
    // handle error
}
String loginUrl = matcher.group(1);

// 3. 提交登陆表单
HttpPost httpPost = new HttpPost(loginUrl);
List<NameValuePair> nameValuePairs = new ArrayList<>();
nameValuePairs.add(new BasicNameValuePair("username", "{username}"));
nameValuePairs.
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值