使用已配置的 JAAS 主题来验证 HttpURLConnection?

Using a configured JAAS subject to authenticate a HttpURLConnection?

过去有几次,我不得不在 WebSphere Application Server 上的应用 运行 中建立经过身份验证的 HTTP 或 HTTPS 连接。
我通常创建了一些自定义的方式来存储连接的用户名和密码 - 使用文本或 XML 文件,或者为了测试,只是 hard-coding - 并将这些详细信息添加到授权 header 在 HttpURLConnection 中,执行 HTTP 基本身份验证。

我最近考虑到 WAS Integrated Solutions Console 有一种配置用户名和密码的方法(在安全 -> Java 身份验证和授权服务 -> J2C 身份验证数据下),这很有意义使用 built-in 功能(如果可能),而不是总是以自定义方式执行此操作,但我在搜索了大约一个小时后仍无法弄清楚如何执行此操作。

那么,有人知道是否可以使用配置的 WAS J2C 身份验证数据来验证任意 HTTP 或 HTTPS 连接吗?

我认为它需要 WebSphere API 才能:

此外:如果 Apache HttpClient 能让这一切变得更容易,我可以使用它,但仍然需要适当的 WebSphere API。

我找到了一个可能对 WebSphere Portal (com.ibm.wps.portletservice.credentialvault.credentials.LtpaTokenCredential) 有用的 class,但我需要在 non-Portal 环境中执行此操作,因此我无法使用任何 Portal-specific classes 或接口。

我还需要它至少在以下类型的应用程序中工作:Servlet 和 WebSphere 信任关联拦截器。

我刚刚在 servlet 中尝试了以下 (Modified from here),它成功地获取了 auth 别名 user/pwd。

import com.ibm.websphere.security.NotImplementedException;
import com.ibm.wsspi.security.auth.callback.Constants;
import com.ibm.wsspi.security.auth.callback.WSMappingCallbackHandlerFactory;
import javax.resource.spi.security.PasswordCredential;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;

Map map = new HashMap();
map.put(Constants.MAPPING_ALIAS, "REPLACE_WITH_YOUR_AUTH_ALIAS");
CallbackHandler callbackHandler = null;
try {
    callbackHandler = WSMappingCallbackHandlerFactory.getInstance().getCallbackHandler(map, null);
} catch (NotImplementedException e) {
}

LoginContext loginContext = null;
try {
loginContext = new LoginContext("DefaultPrincipalMapping", callbackHandler);
    loginContext.login();
} catch (LoginException e) {
}

Subject subject = loginContext.getSubject();
Set credentials = subject.getPrivateCredentials();

PasswordCredential passwordCredential = (PasswordCredential) credentials.iterator().next();

String user = passwordCredential.getUserName();
String password = new String(passwordCredential.getPassword());

response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<h1>User: " + user + " --- Password: " + password+"</h1>");

如果身份验证是在 WAS 服务器之间进行的,则无需费力;只要参与的 WAS 服务器构成同一安全域的一部分并相互信任,LTPA 令牌就足够了。

如果你的想法是从非WAS服务器转到WAS服务器,你可以看看TAI选项,但你仍然不需要使用Authentication Aliases。

当我们从一项服务向下游服务进行身份验证时,我们只需传入 LTPA 令牌,如下所示(LTPA 令牌不是 Portal 的东西,它是 WAS 的东西)。假设有人已经在您的服务上进行了身份验证,例如从 Portal 或 WAS 登录,我们想调用另一台 WAS 服务器上的下游 REST 服务。

/** For call to a REST client, use apache wink that comes with WAS:
* This method shows how to pass in the available LTPA token to create
* a RestClient
private org.apache.wink.client.RestClient getRestClient() {
  if (restClient == null) {
    org.apache.wink.client.ClientConfig config = new ClientConfig();    
    config.handlers(new org.apache.wink.client.handlers.LtpaAuthSecurityHandler());
    restClient = new RestClient(config);
  }
  return restClient;
}