我有一个简单的 POJO 作为映射到的 web 服务,可以说 /public/authenticate :
WebService
@SOAPBinding(style = SOAPBinding.Style.DOCUMENT)
public class AuthWS{
@WebMethod
public boolean doAuthenticate(String securityToken) {
....
}
}
此 Web 服务不需要身份验证,也不是受保护的资源。
我确实有其他私有网络服务映射到路径:/private/ws/*;
目前,我使用具有数据库登录模块设置的安全域。它工作正常,但用户首先需要通过基于向 /j_security_check 发出发布请求的 Web 表单进行身份验证。只有经过此步骤,用户才能使用其他私有 Web 服务。
我想在客户端调用此 doAuthenticate 方法后以编程方式执行身份验证。以便客户端能够调用其他 /private/ws/* webservice 方法。
我将输入我想要实现的目标:
@WebService
@SOAPBinding(style = SOAPBinding.Style.DOCUMENT)
public class AuthWS{
@WebMethod
public boolean doAuthenticate(String securityToken) {
SomeSecurityManager manager= SomeSecurityManager.getDefaultManager()
Map<String,Object> map = new HashMap<String, Object>();
map.put("MY_CUSTOM_SECURITY_TOKEN",securityToken);
manager.doLogin(map);
// after webservice method returns, client should now be able to invoke other private webservice
// this means that the manager should associate with this session an authenticated user.
// in order that authorization to work.
}
}
还有我的 CustomLoginModule :
class CustomLogModule implements LoginModule {
...
public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) {
// store what's needed
}
public boolean login(){
// get securityToken send from the SomeSecurityManager and validate it.
// get user information from that token and store into Subject object.
}
}
在我的实现 JAAS LoginModule 的 CustomLoginModule 中,使用自定义逻辑检查 securityToken,例如验证它是否使用公钥正确签名。该 securityToken 包含有关主体的信息。
如果您需要更多详细信息,请随时询问。
谢谢。
已编辑
1.) 与 module.xml 一起创建 custom-login-module.jar
<module xmlns="urn:jboss:module:1.1" name="custom.login.module">
<resources>
<resource-root path="custom-login-module.jar"/>
</resources>
<dependencies>
<module name="org.picketbox"/>
<module name="javax.api"/>
<module name="org.slf4j"/>
</dependencies>
</module>
2.) 将 custom-login-module.jar 和 module.xml 添加到 jboss-as-7.1.1.Final\modules\custom\login\module
3.) custom-login-module.jar 包含: public class CustomCallbackHandler implements CallbackHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(CustomCallbackHandler.class);
private String token;
public CustomCallbackHandler(String token) {
this.token= token;
}
public String getToken() {
return token;
}
@Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (Callback callback : callbacks) {
if (callback instanceof TokenCallback) {
((TokenCallback) callback).setToken(token);
}
}
}
}
public class TokenCallback implements Callback {
private static final Logger LOGGER = LoggerFactory.getLogger(TokenCallback.class);
private String token;
public TokenCallback() {
}
public String getToken() {
return token;
}
public void setToken(String token) {
LOGGER.info("Setting token = " + token);
this.token = token;
}
}
public class CustomLoginModule extends AbstractServerLoginModule {
private static final Logger LOGGER = LoggerFactory.getLogger(CustomLoginModule.class);
@Override
public boolean login() throws LoginException {
LOGGER.info("Doing login()");
boolean login = super.login();
super.loginOk = true;
return login;
}
@Override
protected Principal getIdentity() {
return new UserPrincipal("some user");
}
@Override
protected Group[] getRoleSets() throws LoginException {
return new Group[]{new MyGroup()}; // that and has name 'dummy'
}
}
这些只是虚拟实现。
我的 Web 应用程序是从 .war 存档中部署的。它包含以下内容:jboss-web.xml
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE jboss-web
PUBLIC -//JBoss//DTD Web Application 2.3V2//EN
http://www.jboss.org/j2ee/dtd/jboss-web_3_2.dtd>
<jboss-web>
<security-domain>custom-auth</security-domain>
</jboss-web>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>WebApp</display-name>
<session-config>
<session-timeout>120</session-timeout>
</session-config>
<security-constraint>
<web-resource-collection>
<web-resource-name>All resources</web-resource-name>
<description>Protects all private resources</description>
<url-pattern>/private/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>dummy</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<security-role>
<role-name>dummy</role-name>
</security-role>
<servlet>
<servlet-name>Private</servlet-name>
<servlet-class>com.company.private.PrivateWs</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Private</servlet-name>
<url-pattern>/private/PrivateWs</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>AuthWS</servlet-name>
<servlet-class>com.company.auth.AuthWS</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AuthWS</servlet-name>
<url-pattern>/AuthWS</url-pattern>
</servlet-mapping>
</web-app>
@WebService
@SOAPBinding(style = SOAPBinding.Style.DOCUMENT)
public class AuthWS{
private static final Logger LOGGER = LoggerFactory.getLogger(AuthWS.class);
@WebMethod
public boolean doAuthenticate(String token) {
tryProgrammaticLogin(token);
return true;
}
private void tryProgrammaticLogin(String token) {
LoginContext loginContext = null;
try {
loginContext = new LoginContext("custom-auth", new CustomCallbackHandler(token));
loginContext.login();
} catch (LoginException e) {
LOGGER.info("Some problem occured when trying to custom login.", e);
}
}
}
从我的 ws 客户端调用 doAuthenticate 有效,但问题是在尝试 ProgrammaticLogin 后发生异常。而且客户无法访问 PrivateWS。
17:33:40,901 INFO [com.mycompany.AuthWS] (http--0.0.0.0-8080-1) Some problem occured when trying to custom login.: javax.security.auth.login.LoginException: Login Failure: all modules ignored
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:921) [rt.jar:1.6.0_26]
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:186) [rt.jar:1.6.0_26]
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:683) [rt.jar:1.6.0_26]
at java.security.AccessController.doPrivileged(Native Method) [rt.jar:1.6.0_26]
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680) [rt.jar:1.6.0_26]
at javax.security.auth.login.LoginContext.login(LoginContext.java:579) [rt.jar:1.6.0_26]
jboss 配置目录中的standalone.xml 包含:
<security-domain name="custom-auth">
<authentication>
<login-module code="com.mycompany.CustomLoginModule" flag="required" module="custom.login.module"/>
</authentication>
</security-domain>
请告诉我通过创建新的 LoginContext 对象进行身份验证的方式是否正确。我不明白为什么会出现这个问题。