我正在尝试从 AdapterAuthentication 迁移到使用 LTPA 将 userRegistry 推迟到 Websphere 容器。
我在这里遵循了入门配置,这里是 Stack Overflow 。我相信选项 2 是本文档中的正确方法。
我已经建立了一个独立的基于 Liberty 配置文件的工作灯实例(使用 6.2)。我已修改 authenticationConfig.xml 以使用 LTPA:
<customSecurityTest name="LTPASecurityTest">
<test realm="wl_directUpdateRealm" step="1" />
<test realm="WASLTPARealm" isInternalUserID="true" />
</customSecurityTest>
<realm name="WASLTPARealm" loginModule="WASLTPAModule">
<className>
com.worklight.core.auth.ext.WebSphereFormBasedAuthenticator</className>
<parameter name="login-page" value="conf/login.html" />
<parameter name="error-page" value="conf/loginError.html" />
</realm>
<loginModule name="WASLTPAModule">
<className>
com.worklight.core.auth.ext.WebSphereLoginModule</className>
</loginModule>
我已经确认(并重建).war 在根级别以及 conf/ 目录下都有 login.html 和 loginError.html。(此处的文档“必须将这些 HTML 文件添加到 Worklight Server WAR 文件中的根目录”确实需要告诉用户如何在 Worklight Studio 中执行此操作)
我修改了适配器以使用 LTPA 领域:
<procedure name="profile" securityTest="LTPASecurityTest"> </procedure>
我已经根据文档修改了 Liberty Profile 的 server.xml 以添加 appSecurity(屏幕截图仅描述了如何从 Websphere 控制台执行此操作),并绑定到 ldapRegistry
<feature>appSecurity-2.0</feature>
<feature>ldapRegistry-3.0</feature>
但是,从服务器日志中,当客户端启动应用程序时,会报告 40 多个堆栈跟踪实例。从客户端看来,连接到 Worklight 的初始调用似乎被拒绝了。我认为这是因为他们没有 LTPA 令牌。
我的期望是,一旦服务器确定用户正在请求安全资源,就会发出挑战。似乎不是发出挑战,而是抛出 WorkLightAuthenticationException。
我需要添加额外的静态资源吗?是否有其他配置更改?Login.html 永远不会返回给最终用户。
控制台日志:
[ERROR ] FWLSE0059E: Login into realm 'WASLTPAModule' failed. null. [project postal]
com.worklight.server.auth.api.WorkLightAuthenticationException
[ERROR ] FWLSE0117E: Error code: 4, error description: AUTHENTICATION_ERROR, error message: An error occurred while performing authentication using loginModule WASLTPAModule, User Identity {wl_directUpdateRealm=null, SubscribeServlet=null, wl_authenticityRealm=null, AdapterAuthRealm=null, wl_remoteDisableRealm=null, wl_antiXSRFRealm=(name:q0a052t5g02f833ocv0o48e4sv, loginModule:WLAntiXSRFLoginModule), wl_deviceAutoProvisioningRealm=null, wl_deviceNoProvisioningRealm=null, myserver=(name:df680b07-3057-4339-8d94-96a050ff99ed, loginModule:WeakDummy), WASLTPARealm=null, wl_anonymousUserRealm=(name:df680b07-3057-4339-8d94-96a050ff99ed, loginModule:WeakDummy)}. [project XYZ] [project XYZ]
[ERROR ] SRVE0777E: Exception thrown by application class 'com.worklight.core.auth.impl.AuthenticationContext.checkAuthentication:548'
com.worklight.server.auth.api.WorkLightAuthenticationException
at com.worklight.core.auth.impl.AuthenticationContext.checkAuthentication(AuthenticationContext.java:548)
at com.worklight.core.auth.impl.AuthenticationContext.login(AuthenticationContext.java:701)
at com.worklight.core.auth.impl.AuthenticationServiceBean.login(AuthenticationServiceBean.java:120)
at com.worklight.gadgets.serving.handler.LoginOnDemandHandler.doPost(LoginOnDemandHandler.java:68)
at com.worklight.gadgets.serving.GadgetAPIServlet.doGetOrPost(GadgetAPIServlet.java:144)
at com.worklight.gadgets.serving.GadgetAPIServlet.doPost(GadgetAPIServlet.java:107)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:595)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:668)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1240)
at [internal classes]
at com.worklight.core.auth.impl.AuthenticationFilter$1.execute(AuthenticationFilter.java:204)
at com.worklight.core.auth.impl.AuthenticationServiceBean.accessResource(AuthenticationServiceBean.java:76)
at com.worklight.core.auth.impl.AuthenticationFilter.doFilter(AuthenticationFilter.java:208)
at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:194)
at [internal classes]
[ERROR ] FWLSE0020E: Ajax request exception: Environment identity is null or not proven for realm WASLTPARealm [project XYZ]
[ERROR ] FWLSE0117E: Error code: 1, error description: INTERNAL_ERROR, error message: FWLSE0069E: An internal error occurred during gadget request [project XYZ]Environment identity is null or not proven for realm WASLTPARealm, User Identity Not available. [project XYZ]
编辑
回答大卫/西蒙的问题:
我在加载应用程序时明确调用 wl.client.connect(不使用 connectOnStartup)但截至目前我没有等待 onSuccess/onFailure。它在我积压的事情上需要补救;但我怀疑这适用于 AdapterAuth,它应该适用于 LTPA。
我从 AdapterAuth 开始(它有效),切换到 LDAPLoginModule(它有效);为了外部化 LDAP 端点,我们正在切换 LTPA。基于此;请注意,客户端代码比我想要的要复杂一些。
这是客户端挑战处理程序。假设工作灯工厂代码在应用程序启动后几乎立即被触发;随后是适配器调用,它触发质询处理程序代码。
...
angular.module(
'XYZ',
[ 'ionic', 'XYZ.controllers', 'XYZ.services', 'worklight' ])
.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
if (window.StatusBar) {
window.StatusBar.styleDefault();
}
});
})
.constant("authenticationRealm" , "WASLTPARealm");
// .constant("authenticationRealm" , "AdapterAuthRealm");
...
// Provide the Worklight object as an Angular service.
angular.module('worklight', [])
.factory('worklight', ['$window', function($window) {
//for unit testing, these aren't defined. only attempt to connect if we're in a worklight container
if (($window.WL)&& ($window.WL.Client)&&($window.WL.Client.connect)){
$window.WL.Client.connect();
}
return $window.WL;
}])
.factory('worklightAuthenticator', ['worklight', 'authenticationRealm', function(worklight, authenticationRealm){
var authenticator = {};
/* public apis */
authenticator.initLogin = function(){
worklight.Client.login(authenticationRealm);
};
authenticator.setAuthRequiredCallback = function(callback){
this.authRequiredCallback = callback;
};
authenticator.setLoginCompleteCallback = function(callback){
this.loginCompleteCallback = callback;
};
authenticator.setLoginCompleteCallback = function(callback){
this.loginCompleteCallback = callback;
};
// This will need to change as we get closer to USA
authenticator.getFriendlyRealmName= function(){
return (authenticationRealm !== "AdapterAuthRealm")? "Active Directory" : "local";
};
//Failing real abstraction going to assign functions based on what realm is defined
authenticator.submitLogin = (authenticationRealm !== "AdapterAuthRealm") ? function(username, password) {
var reqURL = '/j_security_check';
var options = {};
options.parameters = {
j_username : username,
j_password : password
};
options.headers = {};
authenticator.realmChallengeHandler.submitLoginForm(reqURL, options, authenticator.realmChallengeHandler.handleChallenge);
} : function(username, password) {
var options = {
parameters : [username, password],
adapter : "Security",
procedure : "submitAuthentication"
};
authenticator.realmChallengeHandler
.submitAdapterAuthentication(options, {onSuccess: function(r){window.alert(r);}, onFailure: function(z){console.log(z);}});
}
this._realmChallengeHandler = worklight.Client.createChallengeHandler(authenticationRealm);
this._submitLoginFormCallback = function(response){
var isLoginFormResponse = this._isCustomResponse(response);
if (isLoginFormResponse){
authenticator.handleChallenge(response);
} else {
authenticator.realmChallengeHandler.submitSuccess();
authenticator.loginCompleteCallback();
}
}
//Failing real abstraction going to assign functions based on what realm is defined
this._isCustomResponse = (authenticationRealm !== "AdapterAuthRealm") ? function(response) {
console.log("Challenge Required...", response);
var idx =response.responseText.indexOf("j_security_check") >= 0;
return idx;
} : function(response) {
console.log("Challenge Required...", response);
if (!response || !response.responseJSON || response.responseText === null) {
return false;
}
if (typeof (response.responseJSON.authRequired) !== 'undefined') {
return true;
} else {
return false;
}
} ;
//Failing real abstraction going to assign functions based on what realm is defined
this._handleChallenge = (authenticationRealm !== "AdapterAuthRealm") ? function(response) {
console.log("Handle Challenge", response);
var authRequired = response.responseText.indexOf("j_security_check") >= 0;
if (authRequired === true) {
authenticator.authRequiredCallback(response.responseText);
} else if (authRequired === false) {
console.log("Challenge Not Required");
authenticator.realmChallengeHandler.submitSuccess();
authenticator.loginCompleteCallback();
return false;
}
} : function(response) {
console.log("Handle Challenge", response);
var authRequired = response.responseJSON.authRequired;
if (authRequired === true) {
authenticator.authRequiredCallback(response.responseJSON);
} else if (authRequired === false) {
console.log("Challenge Not Required");
authenticator.realmChallengeHandler.submitSuccess();
authenticator.loginCompleteCallback();
return false;
}
};
this._realmChallengeHandler.isCustomResponse = this._isCustomResponse;
this._realmChallengeHandler.handleChallenge = this._handleChallenge;
this._realmChallengeHandler.submitLoginFormCallback = this._submitLoginFormCallback;
authenticator.realmChallengeHandler = this._realmChallengeHandler;
return authenticator;
}])
;