通过Websphere控制台,我设置了一个策略集和一个策略集绑定,以便在web服务上支持UsernameToken身份验证。正如预期的那样,如果没有正确的用户名和密码,它将拒绝web服务调用。但是,它现在接受连接的LDAP中的每个用户。
我希望能够只允许访问特定LDAP组中的用户。我有一种感觉,我需要在调用者设置中创建一个自定义JAAS登录,但我不完全确定。
有没有人对此有解决方案,或者我应该寻找的方向?
编辑:我这样做是为了公开IBM BPM web服务。基于EJB而不是POJO创建web服务,然后使用@RolesAllowed
注释指定允许从您的服务调用特定方法的角色。使用adminconsole、脚本或绑定文件将定义的角色从LDAP服务器映射到用户或组。
这可能比与Login模块作斗争容易得多,而且更灵活。
您可以创建一个自定义JAAS登录模块,以便在使用用户名令牌时使用。您可以使用JAAS配置,该配置首先调用内置令牌使用者,然后调用自定义使用者。这样做意味着您可以使用内置的消费者来解析令牌并执行时间戳和nonce处理,而您只需要在自己的登录模块中执行用户名/密码验证。
说明可在这里找到:http://www14.software.ibm.com/webapp/wsbroker/redirect?version=phil&product=was-nd-dist&topic=twbs_replace_authmethod_usernametoken
(请原谅格式。我已经尽我所能了
使用堆叠的JAAS登录模块替换UsernameToken使用者的身份验证方法
默认情况下,Web服务安全UsernameToken使用者UNTConsumeLoginModule总是根据WebSphere注册中心验证令牌中包含的用户名和密码。您可以使用GenericSecurityTokenFactory提供的spi来绕过此身份验证方法。
关于此任务
如果您想要替换UNTConsumeLoginModule使用的身份验证方法,您必须提供您自己的自定义JAAS登录模块来执行身份验证。在自定义JAAS配置中,自定义登录模块被堆叠在UNTConsumeLoginModule下。UNTConsumeLoginModule使用并验证令牌XML。为用户名和密码提供的值的验证被延迟到自定义的堆叠登录模块。
因为使用UNTConsumeLoginModule时假定将对用户名和密码进行身份验证,所以对打算执行此功能的堆叠登录模块的需求要比只打算提供动态令牌功能的登录模块的需求多。
要向UNTConsumeLoginModule指示它不应该验证用户名和密码,您必须在配置的回调处理程序上设置以下属性:
com.ibm.wsspi.wssecurity.token.UsernameToken.authDeferred=true
像大多数WS-Security登录模块一样,UNTConsumeLoginModule总是将消费的令牌放在堆栈中所有登录模块都可以访问的共享状态映射中。当authDeferred=true被指定时,在提交阶段,UNTConsumeLoginModule确保最初放在共享状态上的UsernameToken对象被放在共享状态的另一个位置。如果找不到此UsernameToken对象,则会发生LoginException。因此,你不能只在回调处理程序上设置authDeferred=true,而不让附带的登录模块将令牌返回到共享状态。
程序开发JAAS登录模块来进行身份验证,并使其可用于应用程序代码。这个新的登录模块堆栈在com.ibm. wss.wssecurity .wssapi.token. impl.untconsumeloginmodule下。
这个登录模块必须:
- 使用以下方法获取UNTConsumeLoginModule消耗的UsernameToken。
用户名
Token unt = UsernameToken)factory.getConsumerTokenFromSharedState(sharedState,UsernameToken.ValueType);
在这个代码示例中,factory是com.ibm.websphere.wssecurity.wssapi.token.GenericSecurityTokenFactory的实例。
按您选择的方式检查用户名和密码
可以调用unt.getUsername()和unt.getPassword()来获取用户名和密码。
如果有一个身份验证错误,你的登录模块应该抛出一个LoginException。
将在上一子步骤中获得的UsernameToken放回到共享状态
使用以下方法将UsernameToken放回共享状态。
工厂。putAuthenticatedTokenToSharedState (sharedState,螺母);
登录模块示例如下:
package test.tokens;
import com.ibm.websphere.wssecurity.wssapi.token.GenericSecurityTokenFactory;
import com.ibm.websphere.wssecurity.wssapi.WSSUtilFactory;
import java.util.HashMap;
import java.util.Map;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
import com.ibm.websphere.wssecurity.wssapi.token.UsernameToken;
import java.util.ArrayList;
import com.ibm.wsspi.security.registry.RegistryHelper;
import com.ibm.websphere.security.UserRegistry;
public class MyUntAuthenticator implements LoginModule {
private Map _sharedState;
private Map _options;
private CallbackHandler _handler;
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map<String, ?> sharedState, Map<String, ?> options) {
this._handler = callbackHandler;
this._sharedState = sharedState;
this._options = options;
}
public boolean login() throws LoginException {
//For the sake of readability, this login module does not
//protect against all NPE's
GenericSecurityTokenFactory factory = null;
WSSUtilFactory utilFactory = null;
try {
factory = GenericSecurityTokenFactory.getInstance();
utilFactory = WSSUtilFactory.getInstance();
} catch (Exception e) {
throw new LoginException(e.toString());
}
if (factory == null) {
throw new LoginException("GenericSecurityTokenFactory.getInstance() returned null");
}
UsernameToken unt = (UsernameToken)factory.getConsumerTokenFromSharedState(this._sharedState,UsernameToken.ValueType);
String username = unt.getUsername();
char [] password = unt.getPassword();
//authenticate the username and password
//to validate a PasswordDigest password (fixpack 8.5.5.8 and later)
//String pw = yourCodeToLookUpPasswordForUsername(username);
//boolean match = utilFactory.verifyDigestedPassword(unt, pw.toCharArray());
//if (!match) throw new LoginException("Digested passwords do not match");
//Example:
try {
simpleUserGroupCheck(username, password, "cn=group1,o=ibm,c=us");
} catch (Exception e) {
LoginException le = new LoginException(e.getMessage());
le.initCause(e);
throw le;
}
//Put the authenticated token to the shared state
factory.putAuthenticatedTokenToSharedState(this._sharedState, unt);
return true;
}
private boolean simpleUserGroupCheck(String username, char [] password, String group) throws Exception {
String allowedGroup = null;
//get the default user registry
UserRegistry user_reg = RegistryHelper.getUserRegistry(null);
//authenticate the user against the user registry
user_reg.checkPassword(username, new String(password));
//get the list of groups that the user belongs to
java.util.List<String> groupList = user_reg.getGroupsForUser(username);
//you can either use a hard-coded group
allowedGroup = group;
//or get the value from your own custom property on the callback handler
//WSSUtilFactory util = WSSUtilFactory.getInstance();
//Map map = util.getCallbackHandlerProperties(this._handler);
//allowedGroup = (String) map.get("MY_ALLOWED_GROUP_1");
//check if the user belongs to an allowed group
if (!groupList.contains(allowedGroup)) {
throw new LoginException("user ["+username+"] is not in allowed group ["+allowedGroup+"]");
}
return true;
}
//implement the rest of the methods required by the
//LoginModule interface
}
创建新的JAAS登录配置
- 在管理控制台中,选择"Security> Global Security"。
- 在"Authentication"下选择"Java Authentication and Authorization Service"。
- 选择System login .
- 单击"新建",然后指定Alias = test. consumer .unt.
- 点击新建,然后指定模块类名= com.ibm. wss.wssecurity .wssapi.token. impl.untconsumeloginmodule
- 单击OK。
- 点击新建,然后指定模块类名= test.tokens.MyUntAuthenticator
- 选择使用登录模块代理
- 单击确定,然后单击保存。
配置您的UsernameToken令牌消费者以使用新的JAAS配置。
- 打开你想要更改的绑定配置
- 在管理控制台中,选择WS-Security> Authentication and protection。
- 在Authentication tokens下,选择要更改的UsernameToken入站令牌。
- 选择JAAS login = test. consumer .unt.
在为UsernameToken消费者配置的回调处理程序上设置所需的属性。
- 点击回调处理程序
- 添加com.ibm.wsspi.wssecurity.token.UsernameToken。authDeferred=true自定义属性
- 单击OK。
单击SAVE。
- 重新启动应用程序服务器以应用JAAS配置更改。
- 测试你的服务