通过 WSO2ESB 访问 NTLM 安全 WS
Access NTLM Secured WS Througth WSO2ESB
大家好,我正在尝试在 WSO2ESB 上设置代理服务以访问 NTLMv2 安全 WS。我创建了一个调解器 class 来实现这一点,但到目前为止运气不好,我一直收到 401 状态
这是代码。
代理服务:
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="test"
transports="http"
statistics="disable"
trace="disable"
startOnLoad="true">
<target endpoint="fincasEP">
<inSequence>
<class name="com.aig.mediator.NTLMAuthMediator">
<property name="port" value="remote-port"/>
<property name="username" value="username-credential"/>
<property name="host" value="remote-host-ip"/>
<property name="domain" value="remot-host-domain"/>
<property name="password" value="**********"/>
</class>
</inSequence>
</target>
<publishWSDL key="fincas-wsdl"/>
<description/>
</proxy>
调解员Class:
public class NTLMAuthMediator extends AbstractMediator {
private String domain;
private String host;
private String port;
private String username;
private String password;
public boolean mediate(MessageContext context) {
org.apache.axis2.context.MessageContext axis2MsgContext;
axis2MsgContext = ((Axis2MessageContext) context).getAxis2MessageContext();
String authString = (String)tmp.get("Authorization");
HttpTransportProperties.Authenticator auth = new HttpTransportProperties.Authenticator();
setCredentials(auth);
List<String> authSchemes = new ArrayList<String>();
authSchemes.add(HttpTransportProperties.Authenticator.NTLM);
auth.setAuthSchemes(authSchemes);
auth.setPreemptiveAuthentication(true); // send authentication info at once
Options options = new Options();
options.setProperty(HTTPConstants.CHUNKED, "false");
options.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, "true");
options.setProperty(HTTPConstants.AUTHENTICATE, auth);
axis2MsgContext.setOptions(options);
return true;
}
private void setCredentials(Authenticator auth) {
boolean isDomain = this.domain != null ? true : this.domain.trim()
.length() > 0 ? true : false;
boolean isUsername = this.username != null ? true : this.username
.trim().length() > 0 ? true : false;
boolean isPassword = this.password != null ? true : this.password
.trim().length() > 0 ? true : false;
boolean isHost = this.host != null ? true
: this.host.trim().length() > 0 ? true : false;
boolean isPort = this.username != null ? true : this.username.trim()
.length() > 0 ? true : false;
if (!isDomain) {
throw new RuntimeException("Domain parameter must NOT be null");
}
if (!isUsername) {
throw new RuntimeException("Username parameter must NOT be null");
}
if (!isPassword) {
throw new RuntimeException("Password parameter must NOT be null");
}
if (!isHost) {
throw new RuntimeException("Host parameter must NOT be null");
}
if (!isPort) {
throw new RuntimeException("Port parameter must NOT be null");
}
auth.setUsername(this.username);
auth.setPassword(this.password);
auth.setDomain(this.domain);
auth.setRealm(AuthScope.ANY_REALM);
auth.setHost(this.host);
auth.setPort(Integer.valueOf(this.port));
auth.setPreemptiveAuthentication(true);
}
public String getDomain() {
return domain;
}
public void setDomain(String domain) {
this.domain = domain;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getPort() {
return port;
}
public void setPort(String port) {
this.port = port;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
我使用的是 wso2esb 最新版本。
WSO2 没有为这种情况提供文档,真是令人沮丧……考虑到 NTLM 是一种旧机制。
如有任何建议,我们将不胜感激
顺便说一句,错误是:
401 - Unauthorized: Access is denied due to invalid credentials.
事实上,我最终可以使用 ESB Mule 解决这个问题,不过我将解释我是如何尝试使用 WSO2ESB 和最后的 MULE 来解决它的...
我正在查看关于 httpclient 的 NTLM,在几个网站之后我注意到 httpclient 3.x 不支持这种类型的机制,这是因为它使用的 NTLMSchema。
我找到了这个 git 回购协议 https://github.com/DovAmir/httpclientAuthHelper 这家伙写了一个 NTLMcuston shema class 与 httpclient 3.x 一起工作的出色工作,我克隆这个回购协议生成jar etc等等,然后我修改了下面的class
org.apache.axis2.transport.http.AbstractHTTPSender
...
...
...
protected void setAuthenticationInfo(HttpClient agent, MessageContext msgCtx, HostConfiguration config)
throws AxisFault, UnknownHostException
{
String localhost = InetAddress.getLocalHost().getHostName().toUpperCase();
...
...
if (domain != null) {
creds = new NTCredentials(username, password, localhost, domain);
} else {
creds = new UsernamePasswordCredentials(username, password);
}
tmpHttpState.setCredentials(new AuthScope(host, port, realm), creds);
}
...
然后编写了一个测试用例以确保 axis2 ServerClient 确实可以正常工作..并且确实如此。但是...我想我并不真正了解 PassThroughHttpSender 的机制。显然还有其他事情要做,让它工作,我真的没有时间,然后我开始考虑其他事情,然后我意识到我们还有一个 ESB Mule 3.4.0 CE 实例 运行...
我只需要修改 class
HttpConnector
{
...
...
// Properties added to enable NTLMv2 Auth
private String ntlmUser;
private String ntlmPassword;
private String ntlmDomain;
private String ntlmHost;
private String ntlmPort;
private boolean ntlmAuthentication;
//getters and setters
protected HttpClient doClientConnect() throws Exception
{
HttpState state = new HttpState();
HttpClient client = new HttpClient();
String localhost = InetAddress.getLocalHost().getHostName();
//TODO setting domain as well.
Credentials credentials;
if (getProxyUsername() != null || getNtlmUser() != null)
{
if (isProxyNtlmAuthentication())
{
credentials = new NTCredentials(getProxyUsername(), getProxyPassword(), localhost, "");
AuthScope authscope = new AuthScope(getProxyHostname(), getProxyPort());
state.setProxyCredentials(authscope, credentials);
}
else if(isNtlmAuthentication()){
AuthPolicy.registerAuthScheme(AuthPolicy.NTLM, CustomNTLM2Scheme.class);
AuthScope authscope = new AuthScope(getNtlmHost(), Integer.valueOf(getNtlmPort()));
credentials = new NTCredentials(getNtlmUser(), getNtlmPassword(), localhost, getNtlmDomain());
state.setCredentials(authscope, credentials);
}
else
{
credentials = new UsernamePasswordCredentials(getProxyUsername(), getProxyPassword());
AuthScope authscope = new AuthScope(getProxyHostname(), getProxyPort());
state.setProxyCredentials(authscope, credentials);
}
}
client.setState(state);
client.setHttpConnectionManager(getClientConnectionManager());
return client;
}
这个流程是:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans" version="CE-3.4.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:pattern="http://www.mulesoft.org/schema/mule/pattern"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/pattern http://www.mulesoft.org/schema/mule/pattern/current/mule-pattern.xsd">
<http:connector name="ntlmconn"
doc:name="HTTP-HTTPS">
<spring:property name="ntlmAuthentication" value="${ntlm.auth}"/>
<spring:property name="ntlmUser" value="${ntlm.username}"/>
<spring:property name="ntlmPassword" value="${ntlm.password}"/>
<spring:property name="ntlmHost" value="${ntlm.host}"/>
<spring:property name="ntlmPort" value="${ntlm.port}"/>
<spring:property name="ntlmDomain" value="${ntlm.domain}"/>
</http:connector>
<pattern:web-service-proxy name="fincas-service"
wsdlFile="${fincas.wsdl}">
<http:inbound-endpoint address="http://localhost:8080/fincas" />
<http:outbound-endpoint address="${endpoint}" connector-ref="ntlmconn"
exchange-pattern="request-response"></http:outbound-endpoint>
</pattern:web-service-proxy>
终于有了这个补丁,我可以让它工作了我在 ESB 上部署了我的 WS,因为服务已经启动,运行我可以花更多的时间来寻找 WSO2ESB 的解决方案。
我希望它也对你有用。
大家好,我正在尝试在 WSO2ESB 上设置代理服务以访问 NTLMv2 安全 WS。我创建了一个调解器 class 来实现这一点,但到目前为止运气不好,我一直收到 401 状态
这是代码。
代理服务:
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="test"
transports="http"
statistics="disable"
trace="disable"
startOnLoad="true">
<target endpoint="fincasEP">
<inSequence>
<class name="com.aig.mediator.NTLMAuthMediator">
<property name="port" value="remote-port"/>
<property name="username" value="username-credential"/>
<property name="host" value="remote-host-ip"/>
<property name="domain" value="remot-host-domain"/>
<property name="password" value="**********"/>
</class>
</inSequence>
</target>
<publishWSDL key="fincas-wsdl"/>
<description/>
</proxy>
调解员Class:
public class NTLMAuthMediator extends AbstractMediator {
private String domain;
private String host;
private String port;
private String username;
private String password;
public boolean mediate(MessageContext context) {
org.apache.axis2.context.MessageContext axis2MsgContext;
axis2MsgContext = ((Axis2MessageContext) context).getAxis2MessageContext();
String authString = (String)tmp.get("Authorization");
HttpTransportProperties.Authenticator auth = new HttpTransportProperties.Authenticator();
setCredentials(auth);
List<String> authSchemes = new ArrayList<String>();
authSchemes.add(HttpTransportProperties.Authenticator.NTLM);
auth.setAuthSchemes(authSchemes);
auth.setPreemptiveAuthentication(true); // send authentication info at once
Options options = new Options();
options.setProperty(HTTPConstants.CHUNKED, "false");
options.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, "true");
options.setProperty(HTTPConstants.AUTHENTICATE, auth);
axis2MsgContext.setOptions(options);
return true;
}
private void setCredentials(Authenticator auth) {
boolean isDomain = this.domain != null ? true : this.domain.trim()
.length() > 0 ? true : false;
boolean isUsername = this.username != null ? true : this.username
.trim().length() > 0 ? true : false;
boolean isPassword = this.password != null ? true : this.password
.trim().length() > 0 ? true : false;
boolean isHost = this.host != null ? true
: this.host.trim().length() > 0 ? true : false;
boolean isPort = this.username != null ? true : this.username.trim()
.length() > 0 ? true : false;
if (!isDomain) {
throw new RuntimeException("Domain parameter must NOT be null");
}
if (!isUsername) {
throw new RuntimeException("Username parameter must NOT be null");
}
if (!isPassword) {
throw new RuntimeException("Password parameter must NOT be null");
}
if (!isHost) {
throw new RuntimeException("Host parameter must NOT be null");
}
if (!isPort) {
throw new RuntimeException("Port parameter must NOT be null");
}
auth.setUsername(this.username);
auth.setPassword(this.password);
auth.setDomain(this.domain);
auth.setRealm(AuthScope.ANY_REALM);
auth.setHost(this.host);
auth.setPort(Integer.valueOf(this.port));
auth.setPreemptiveAuthentication(true);
}
public String getDomain() {
return domain;
}
public void setDomain(String domain) {
this.domain = domain;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getPort() {
return port;
}
public void setPort(String port) {
this.port = port;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
我使用的是 wso2esb 最新版本。
WSO2 没有为这种情况提供文档,真是令人沮丧……考虑到 NTLM 是一种旧机制。
如有任何建议,我们将不胜感激
顺便说一句,错误是:
401 - Unauthorized: Access is denied due to invalid credentials.
事实上,我最终可以使用 ESB Mule 解决这个问题,不过我将解释我是如何尝试使用 WSO2ESB 和最后的 MULE 来解决它的...
我正在查看关于 httpclient 的 NTLM,在几个网站之后我注意到 httpclient 3.x 不支持这种类型的机制,这是因为它使用的 NTLMSchema。
我找到了这个 git 回购协议 https://github.com/DovAmir/httpclientAuthHelper 这家伙写了一个 NTLMcuston shema class 与 httpclient 3.x 一起工作的出色工作,我克隆这个回购协议生成jar etc等等,然后我修改了下面的class
org.apache.axis2.transport.http.AbstractHTTPSender
...
...
...
protected void setAuthenticationInfo(HttpClient agent, MessageContext msgCtx, HostConfiguration config)
throws AxisFault, UnknownHostException
{
String localhost = InetAddress.getLocalHost().getHostName().toUpperCase();
...
...
if (domain != null) {
creds = new NTCredentials(username, password, localhost, domain);
} else {
creds = new UsernamePasswordCredentials(username, password);
}
tmpHttpState.setCredentials(new AuthScope(host, port, realm), creds);
}
...
然后编写了一个测试用例以确保 axis2 ServerClient 确实可以正常工作..并且确实如此。但是...我想我并不真正了解 PassThroughHttpSender 的机制。显然还有其他事情要做,让它工作,我真的没有时间,然后我开始考虑其他事情,然后我意识到我们还有一个 ESB Mule 3.4.0 CE 实例 运行...
我只需要修改 class
HttpConnector
{
...
...
// Properties added to enable NTLMv2 Auth
private String ntlmUser;
private String ntlmPassword;
private String ntlmDomain;
private String ntlmHost;
private String ntlmPort;
private boolean ntlmAuthentication;
//getters and setters
protected HttpClient doClientConnect() throws Exception
{
HttpState state = new HttpState();
HttpClient client = new HttpClient();
String localhost = InetAddress.getLocalHost().getHostName();
//TODO setting domain as well.
Credentials credentials;
if (getProxyUsername() != null || getNtlmUser() != null)
{
if (isProxyNtlmAuthentication())
{
credentials = new NTCredentials(getProxyUsername(), getProxyPassword(), localhost, "");
AuthScope authscope = new AuthScope(getProxyHostname(), getProxyPort());
state.setProxyCredentials(authscope, credentials);
}
else if(isNtlmAuthentication()){
AuthPolicy.registerAuthScheme(AuthPolicy.NTLM, CustomNTLM2Scheme.class);
AuthScope authscope = new AuthScope(getNtlmHost(), Integer.valueOf(getNtlmPort()));
credentials = new NTCredentials(getNtlmUser(), getNtlmPassword(), localhost, getNtlmDomain());
state.setCredentials(authscope, credentials);
}
else
{
credentials = new UsernamePasswordCredentials(getProxyUsername(), getProxyPassword());
AuthScope authscope = new AuthScope(getProxyHostname(), getProxyPort());
state.setProxyCredentials(authscope, credentials);
}
}
client.setState(state);
client.setHttpConnectionManager(getClientConnectionManager());
return client;
}
这个流程是:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans" version="CE-3.4.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:pattern="http://www.mulesoft.org/schema/mule/pattern"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/pattern http://www.mulesoft.org/schema/mule/pattern/current/mule-pattern.xsd">
<http:connector name="ntlmconn"
doc:name="HTTP-HTTPS">
<spring:property name="ntlmAuthentication" value="${ntlm.auth}"/>
<spring:property name="ntlmUser" value="${ntlm.username}"/>
<spring:property name="ntlmPassword" value="${ntlm.password}"/>
<spring:property name="ntlmHost" value="${ntlm.host}"/>
<spring:property name="ntlmPort" value="${ntlm.port}"/>
<spring:property name="ntlmDomain" value="${ntlm.domain}"/>
</http:connector>
<pattern:web-service-proxy name="fincas-service"
wsdlFile="${fincas.wsdl}">
<http:inbound-endpoint address="http://localhost:8080/fincas" />
<http:outbound-endpoint address="${endpoint}" connector-ref="ntlmconn"
exchange-pattern="request-response"></http:outbound-endpoint>
</pattern:web-service-proxy>
终于有了这个补丁,我可以让它工作了我在 ESB 上部署了我的 WS,因为服务已经启动,运行我可以花更多的时间来寻找 WSO2ESB 的解决方案。
我希望它也对你有用。