java.lang.IllegalStateException:必需属性为null,AtomicServiceReference [name = clientAuthenticationService,ctx = null,ref = null,svc = null]

时间:2017-12-28 08:55:18

标签: java websphere websphere-liberty

我正在编写一个测试演示来测试Liberty 17.0.0.3上的客户端到服务器连接。

在WebSphere 8.5.5.11上,客户端测试演示代码如下所示:

public class DSLoginConfiguration extends Configuration
{
    public AppConfigurationEntry[] getAppConfigurationEntry(java.lang.String applicationName)
    {
        Hashtable<String, String> h = new Hashtable<String, String>();
        h.put("delegate", "com.ibm.ws.security.common.auth.module.WSClientLoginModuleImpl");
        AppConfigurationEntry entry = new AppConfigurationEntry(
                "com.ibm.ws.security.common.auth.module.proxy.WSLoginModuleProxy",
                AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, h);
        return new AppConfigurationEntry[] { entry };
    }

    public void refresh()
    {

    }
}


public class RMITest {

    private String hostName;
    private String password;
    private String userName;
    private InitialContext initialContext;

    public RMITest(String hostName, String userName, String password) {
        this.hostName = hostName;
        this.userName = userName;
        this.password = password;
    }

    protected LoginContext createLoginContext(String userName, String password) throws Exception {
        Configuration config = new DSLoginConfiguration();
        Configuration.setConfiguration(config);
        LoginContext loginContext = new LoginContext("ClientContainer",
            new WSCallbackHandlerImpl(userName, "customRealm", password));
        return loginContext;
    }

    private void loginRMIproxy() throws Exception {
        LoginContext lc = createLoginContext(userName, password);
        lc.login();
        Subject s = lc.getSubject();
        System.out.println("*****Subject*****" + s);
        System.out.println("*****Principals*****" + s.getPrincipals());
        System.out.println(s.getPrincipals().size());
        WSSubject.setRunAsSubject(s);
    }

    protected void runTest() {
        try {
            System.out.println("************** Begin RMI Test **************");
            loginRMIproxy();
            System.out.println("************** End RMI Test **************");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

public class HelloWorldClient {
    public static void main(String[] args) throws Exception {
        String hostName = "localhost";
        String userName = "quoc";
        String password = "April";

        RMITest rmiTest = new RMITest(hostName, userName, password);
        rmiTest.runTest();
    }
}

它可以成功连接。但是当我在Liberty上测试这个客户端演示代码时,它会抛出以下异常:

javax.security.auth.login.LoginException: unable to find LoginModule class: com.ibm.ws.security.common.auth.module.proxy.WSLoginModuleProxy
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:828)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:196)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:698)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:696)
at java.security.AccessController.doPrivileged(AccessController.java:650)
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:696)
at javax.security.auth.login.LoginContext.login(LoginContext.java:597)
at com.client.RMITest.loginRMIproxy(RMITest.java:73)
at com.client.RMITest.runTest(RMITest.java:86)
at com.client.HelloWorldClient.main(HelloWorldClient.java:19)

我发现类WSLoginModuleProxy在Liberty上有不同的包。所以我改变了类DSLoginConfiguration,如下所示:

public class DSLoginConfiguration extends Configuration
{
    public AppConfigurationEntry[] getAppConfigurationEntry(java.lang.String applicationName)
    {
        Hashtable<String, String> h = new Hashtable<String, String>();
        h.put("delegate", "com.ibm.ws.security.client.jaas.modules.WSClientLoginModuleImpl");
        AppConfigurationEntry entry = new AppConfigurationEntry(
                "com.ibm.ws.security.jaas.common.modules.WSLoginModuleProxy",
                AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, h);
        return new AppConfigurationEntry[] { entry };
    }

    public void refresh()
    {

    }
}

但它仍然会抛出异常

javax.security.auth.login.LoginException: java.lang.ClassCastException: java.lang.String incompatible with java.lang.Class
at com.ibm.ws.security.jaas.common.modules.WSLoginModuleProxy.initialize(WSLoginModuleProxy.java:83)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:90)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
at java.lang.reflect.Method.invoke(Method.java:508)
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:774)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:196)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:698)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:696)
at java.security.AccessController.doPrivileged(AccessController.java:650)
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:696)
at javax.security.auth.login.LoginContext.login(LoginContext.java:597)
at com.client.RMITest.loginRMIproxy(RMITest.java:74)
at com.client.RMITest.runTest(RMITest.java:87)
at com.client.HelloWorldClient.main(HelloWorldClient.java:19)

at javax.security.auth.login.LoginContext.invoke(LoginContext.java:890)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:196)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:698)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:696)
at java.security.AccessController.doPrivileged(AccessController.java:650)
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:696)
at javax.security.auth.login.LoginContext.login(LoginContext.java:597)
at com.client.RMITest.loginRMIproxy(RMITest.java:74)
at com.client.RMITest.runTest(RMITest.java:87)
at com.client.HelloWorldClient.main(HelloWorldClient.java:19)

然后我发现有不同的方法通过反编译jar包在WebSphere和Liberty上获取类WSClientLoginModuleImpl。所以我再次更改类DSLoginConfiguration,如下所示:

public class DSLoginConfiguration extends Configuration {
    public AppConfigurationEntry[] getAppConfigurationEntry(java.lang.String applicationName) {
        WSClientLoginModuleImpl loginModuleImpl = new WSClientLoginModuleImpl();
        Hashtable<String, Class> h = new Hashtable<String, Class>();
        h.put("delegate", loginModuleImpl.getClass());
        AppConfigurationEntry entry = new AppConfigurationEntry(
                "com.ibm.ws.security.jaas.common.modules.WSLoginModuleProxy",
                AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, h);
        return new AppConfigurationEntry[] { entry };
    }

    public void refresh() {

    }
}

然后它仍然抛出如下的异常:

javax.security.auth.login.LoginException: java.lang.IllegalStateException: Required attribute is null,AtomicServiceReference[name=clientAuthenticationService,ctx=null,ref=null,svc=null]
at com.ibm.wsspi.kernel.service.utils.AtomicServiceReference.getService(AtomicServiceReference.java:239)
at com.ibm.wsspi.kernel.service.utils.AtomicServiceReference.getServiceWithException(AtomicServiceReference.java:210)
at com.ibm.ws.security.client.internal.jaas.JAASClientService.getClientAuthenticationService(JAASClientService.java:372)
at com.ibm.ws.security.client.jaas.modules.WSClientLoginModuleImpl.login(WSClientLoginModuleImpl.java:110)
at com.ibm.ws.security.jaas.common.modules.WSLoginModuleProxy.login(WSLoginModuleProxy.java:141)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:90)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
at java.lang.reflect.Method.invoke(Method.java:508)
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:788)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:196)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:698)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:696)
at java.security.AccessController.doPrivileged(AccessController.java:650)
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:696)
at javax.security.auth.login.LoginContext.login(LoginContext.java:597)
at com.client.RMITest.loginRMIproxy(RMITest.java:72)
at com.client.RMITest.runTest(RMITest.java:85)
at com.client.HelloWorldClient.main(HelloWorldClient.java:19)

at javax.security.auth.login.LoginContext.invoke(LoginContext.java:890)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:196)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:698)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:696)
at java.security.AccessController.doPrivileged(AccessController.java:650)
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:696)
at javax.security.auth.login.LoginContext.login(LoginContext.java:597)
at com.client.RMITest.loginRMIproxy(RMITest.java:72)
at com.client.RMITest.runTest(RMITest.java:85)
at com.client.HelloWorldClient.main(HelloWorldClient.java:19)

我查了很多文件,但我无法解决,所以我得请求帮助。

是否有人知道如何解决此问题或如何使用自定义LoginModule连接Liberty上的客户端和服务器?

提前致谢。

1 个答案:

答案 0 :(得分:0)

WSClientLoginModuleImpl类不是API,它是Liberty中使用内部OSGi服务的内部类。看到的错误是因为客户端容器中提供的服务不可用。

Liberty中需要客户端容器通过使用“ClientContainer”或“WSLogin”JAAS登录上下文条目创建LoginContext来使用WSClientLoginModuleImpl。