A client running on WSAD 5 (or Websphere Thin Application Client) tries
to open a connection on Websphere 5.0 with security enabled (and Java 2
security disabled).
My code snipsnet is:
Hashtable ht = new Hashtable();
ht.put(Context.PROVIDER_URL, "corbaloc:iiop:pc21180e:2809");
ht.put(
Context.INITIAL_CONTEXT_FACTORY,
"com.ibm.websphere.naming.WsnInitialContextFactory");
ht.put(Context.SECURITY_PRINCIPAL, "aze");
ht.put(Context.SECURITY_CREDENTIALS, "aze");
Context initial;
try {
initial = new InitialContext(ht);
QuoteHome home =
(QuoteHome) PortableRemoteObject.narrow(
initial.lookup("ejb/fr/bdf/testrmi/QuoteHome"),
QuoteHome.class);
Quote quote=home.create();
Quotation q = quote.get();
The error is
com.ibm.websphere.csi.CSIException: SECJ0053E: Authorization failed for
/UNAUTHENTICATED while invoking (Bean)ejb/fr/bdf/testrmi/QuoteHome
get:1 securityName: /UNAUTHENTICATED;accessID: null is not granted any
of the required roles: lecteur
The EJB deployment descriptor defines that role 'lecteur' has access to
method get() in bean Quote.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise
JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd">
<ejb-jar id="ejb-jar_ID">
<display-name>TestRMI</display-name>
<enterprise-beans>
<session id="Quote">
<description>Provides a random quotation</description>
<display-name>Quote</display-name>
<ejb-name>Quote</ejb-name>
<home>fr.bdf.testrmi.QuoteHome</home>
<remote>fr.bdf.testrmi.Quote</remote>
<ejb-class>fr.bdf.testrmi.QuoteBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Bean</transaction-type>
<security-identity>
<description></description>
<run-as>
<description></description>
<role-name>lecteur</role-name>
</run-as>
</security-identity>
</session>
</enterprise-beans>
<assembly-descriptor>
<security-role>
<description>Ce rôle comprend les utilisateurs de l'application. Il
autorise la lecture des citations.</description>
<role-name>lecteur</role-name>
</security-role>
<method-permission>
<role-name>lecteur</role-name>
<method>
<ejb-name>Quote</ejb-name>
<method-intf>Remote</method-intf>
<method-name>get</method-name>
<method-params>
</method-params>
</method>
</method-permission>
</assembly-descriptor>
<ejb-client-jar>TestRMIClient.jar</ejb-client-jar>
</ejb-jar>
I'd appreciate if someone can help me to solve this problem.
--
Régis Décamps
Thanks.
You need to do a JAAS programmatic login, see here:
>
Thanks for your assistance. I spent some time (in vain). I read the
JAAS doc and tried to call the WsSubject and WsLogin API.
I have changed my EJB invocation, to create a LoginContext, just before
creating the Bean:
Context initial = new InitialContext(env);
log.info("Connection on " + env.getProperty(Context.PROVIDER_URL));
log.debug("Performing lookup of " + jndiLookupName);
QuoteHome home =
(QuoteHome) PortableRemoteObject.narrow(
initial.lookup(jndiLookupName),
QuoteHome.class);
login(); // new method to set the WsSubject
log.debug("Creating Quote from home");
quote = home.create();
The new login() method is
private void login() {
Properties env = System.getProperties();
LoginContext lc = null;
try {
lc=
new LoginContext(
"WSLogin",
new WSCallbackHandlerImpl(
(String) env.get(Context.SECURITY_PRINCIPAL),
(String) env.get(Context.SECURITY_CREDENTIALS)));
lc.login();
} catch (LoginException le) {
System.out.println(
"Cannot create LoginContext. " + le.getMessage());
System.exit(1);
} catch (SecurityException se) {
System.out.println("Cannot create LoginContext." + se.getMessage());
System.exit(2);
}
subject=lc.getSubject();
}
The use of the bean itself is made inside doAs:
log.debug("Calling remote method...");
// Invoke a J2EE resource using the authenticated subject
WSSubject.doAs(subject, new java.security.PrivilegedAction() {
public Object run() {
try {
Quotation q = quote.get();
System.out.println(q.getQuote());
if (q.getAuthor() != null && q.getAuthor().length() > 0) {
System.out.println("\t-- " + q.getAuthor());
}
} catch (Exception e) {
log.error(
"error while accessing EJB resource, exception: "
+ e.getMessage());
e.printStackTrace();
}
return null;
}
});
Unfortunately, the error is unchanged.
java -Djava.naming.provider.url=iiop://pc21180e
-Djava.naming.security.principal=was5admin
-Djava.naming.security.credentials=blabla
-Djava.security.auth.login.config="C:\Program Files\IBM\WebSphere
Studio\Application
Developer\v5.1.2\runtimes\base_v5\properties\wsjaas_client.conf"
Fortune
DEBUG [main] (Fortune.java:51) - Context
factory=com.ibm.websphere.naming.WsnInitialContextFactory
INFO [main] (Fortune.java:56) - Connection on iiop://pc21180e
DEBUG [main] (Fortune.java:57) - Performing lookup of
ejb/fr/bdf/testrmi/QuoteHome
DEBUG [P=741908:O=0:CT] (Fortune.java:83) - Creating Quote from home
DEBUG [P=741908:O=0:CT] (Fortune.java:103) - Calling remote method...
java.rmi.ServerException: RemoteException occurred in server thread;
nested exception is:
java.rmi.RemoteException:
Trace from server: 1198777258 at host pc21180e >>
java.rmi.RemoteException: ; nested exception is:
com.ibm.websphere.csi.CSIException: SECJ0053E: Echec d'autorisation de
/UNAUTHENTICATED lors de l'appel de (Bean)ejb/fr/bdf/testrmi/QuoteHome
get:1 securityName: /UNAUTHENTICATED;accessID: null is not granted any
of the required roles: lecteur
com.ibm.websphere.csi.CSIException: SECJ0053E: Echec d'autorisation de
/UNAUTHENTICATED lors de l'appel de (Bean)ejb/fr/bdf/testrmi/QuoteHome
get:1 securityName: /UNAUTHENTICATED;accessID: null is not granted any
of the required roles: lecteur
at
com.ibm.ws.security.core.SecurityCollaborator.performAuthorization(SecurityCollaborator.java:386)
at
com.ibm.ws.security.core.EJSSecurityCollaborator.preInvoke(EJSSecurityCollaborator.java:170)
at
com.ibm.ejs.container.EJSContainer.preInvoke_internal(EJSContainer.java:2572)
at
com.ibm.ejs.container.EJSContainer.preInvoke(EJSContainer.java:2337)
at
com.ibm.ejs.container.EJSContainer.preInvoke(EJSContainer.java:2322)
at
fr.bdf.testrmi.EJSRemoteStatelessQuote_a60fa3c7.get(EJSRemoteStatelessQuote_a60fa3c7.java:21)
at
fr.bdf.testrmi._EJSRemoteStatelessQuote_a60fa3c7_Tie.get(_EJSRemoteStatelessQuote_a60fa3c7_Tie.java:150)
at
fr.bdf.testrmi._EJSRemoteStatelessQuote_a60fa3c7_Tie._invoke(_EJSRemoteStatelessQuote_a60fa3c7_Tie.java:76)
at
com.ibm.CORBA.iiop.ServerDelegate.dispatchInvokeHandler(ServerDelegate.java:615)
at com.ibm.CORBA.iiop.ServerDelegate.dispatch(ServerDelegate.java:468)
at com.ibm.rmi.iiop.ORB.process(ORB.java:396)
at com.ibm.CORBA.iiop.ORB.process(ORB.java:1608)
at com.ibm.rmi.iiop.Connection.doWork(Connection.java:2164)
at com.ibm.rmi.iiop.WorkUnitImpl.doWork(WorkUnitImpl.java:63)
at com.ibm.ejs.oa.pool.PooledThread.run(ThreadPool.java:95)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:593)
<< END server: 1198777258 at host pc21180e
; nested exception is:
com.ibm.websphere.csi.CSIException: SECJ0053E: Echec d'autorisation de
/UNAUTHENTICATED lors de l'appel de (Bean)ejb/fr/bdf/testrmi/QuoteHome
get:1 securityName: /UNAUTHENTICATED;accessID: null is not granted any
of the required roles: lecteur
at
com.ibm.CORBA.iiop.UtilDelegateImpl.mapSystemException(UtilDelegateImpl.java:156)
at javax.rmi.CORBA.Util.mapSystemException(Util.java:83)
at fr.bdf.testrmi._Quote_Stub.get(_Quote_Stub.java:244)
at Fortune$1.run(Fortune.java:111)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:476)
at com.ibm.websphere.security.auth.WSSubject.doAs(WSSubject.java:106)
at Fortune.go(Fortune.java:108)
at Fortune.main(Fortune.java:130)
Caused by: java.rmi.RemoteException:
I really wonder how to pass the identity to the server (accessID: null
is not granted any of the required roles). Do you know how to perform
this action with the Universal Test Client, by the way. I'd like to
have a way to know which of my client or my server is broken.
Thanks,
--
Régis
PS: Sorry for this long post
> I really wonder how to pass the identity to the server (accessID: null
> is not granted any of the required roles). Do you know how to perform
> this action with the Universal Test Client, by the way. I'd like to
> have a way to know which of my client or my server is broken.
A couple of questions ...
1. Do SECURITY_PRINCIPAL and SECURITY_CREDENTIALS contain a valid userid
and password for your user registry?
2. Have you mapped this user, or a group that contains this user, to the
role that is required to call the EJB ?
Paul.
Yes the security principal and credentials are mapped to a valid user
defined with a custom registry.
The proof I have is that the bean is correctly called from within a
Servlet, which is:
Hashtable ht = new Hashtable();
ht.put(Context.PROVIDER_URL, "iiop://pc21180e");
ht.put(
Context.INITIAL_CONTEXT_FACTORY,
"com.ibm.websphere.naming.WsnInitialContextFactory");
Context initial;
try {
initial = new InitialContext(ht);
QuoteHome home =
(QuoteHome) javax.rmi.PortableRemoteObject.narrow (
initial.lookup("ejb/fr/bdf/testrmi/QuoteHome"),
QuoteHome.class);
Quote quote=home.create();
Quotation q = quote.get();
resp.getWriter().print(q.getQuote());
} catch (...)
When the browser requests this servlet, the AppServer requires a login.
Providing a valid principal and credentials displays the quotation.
An incorrect principal and credential fails, and the server logs
[21/02/06 17:28:07:024 CET] 7ffcae1e JaasLoginHelp E SECJ4001E:
L'ouverture de session a échoué pour aze/customRealm
com.ibm.websphere.security.auth.WSLoginFailedException: Password check
failed for user: aze
at
com.ibm.ws.security.server.lm.swamLoginModule.login(swamLoginModule.java:269)
at
com.ibm.ws.security.common.auth.module.proxy.WSLoginModuleProxy.login(WSLoginModuleProxy.java:119)
at java.lang.reflect.Method.invoke(Native Method)
at
javax.security.auth.login.LoginContext.invoke(LoginContext.java:607)
at
javax.security.auth.login.LoginContext.access$000(LoginContext.java:124)
at javax.security.auth.login.LoginContext$3.run(LoginContext.java:543)
at java.security.AccessController.doPrivileged(Native Method)
at
javax.security.auth.login.LoginContext.invokeModule(LoginContext.java:540)
at javax.security.auth.login.LoginContext.login(LoginContext.java:450)
at
com.ibm.ws.security.auth.JaasLoginHelper.jaas_login(JaasLoginHelper.java:169)
at
com.ibm.ws.security.auth.ContextManagerImpl.login(ContextManagerImpl.java:735)
at
com.ibm.ws.security.web.WebAuthenticator.basicAuthenticate(WebAuthenticator.java:1053)
at
com.ibm.ws.security.web.WebAuthenticator.handleBasicAuth(WebAuthenticator.java:741)
at
com.ibm.ws.security.web.WebAuthenticator.authenticate(WebAuthenticator.java:878)
at
com.ibm.ws.security.web.WebCollaborator.authorize(WebCollaborator.java:473)
at
com.ibm.ws.security.web.EJSWebCollaborator.preInvoke(EJSWebCollaborator.java:214)
at
com.ibm.ws.webcontainer.webapp.WebAppSecurityCollaborator.preInvoke(WebAppSecurityCollaborator.java:132)
at
com.ibm.ws.webcontainer.webapp.WebAppRequestDispatcher.dispatch(WebAppRequestDispatcher.java:510)
at
com.ibm.ws.webcontainer.webapp.WebAppRequestDispatcher.forward(WebAppRequestDispatcher.java:176)
at
com.ibm.ws.webcontainer.srt.WebAppInvoker.doForward(WebAppInvoker.java:79)
at
com.ibm.ws.webcontainer.srt.WebAppInvoker.handleInvocationHook(WebAppInvoker.java:201)
at
com.ibm.ws.webcontainer.cache.invocation.CachedInvocation.handleInvocation(CachedInvocation.java:71)
at
com.ibm.ws.webcontainer.cache.invocation.CacheableInvocationContext.invoke(CacheableInvocationContext.java:114)
at
com.ibm.ws.webcontainer.srp.ServletRequestProcessor.dispatchByURI(ServletRequestProcessor.java:186)
at
com.ibm.ws.webcontainer.oselistener.OSEListenerDispatcher.service(OSEListener.java:334)
at
com.ibm.ws.webcontainer.http.HttpConnection.handleRequest(HttpConnection.java:56)
at
com.ibm.ws.http.HttpConnection.readAndHandleRequest(HttpConnection.java:610)
at com.ibm.ws.http.HttpConnection.run(HttpConnection.java:431)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java(Compiled
Code))
--------------------------------------------------------------------------------
com.ibm.websphere.security.PasswordCheckFailedException: Password check
failed for user: aze
--------------------------------------------------------------------------------
Do you have any other suggestion?
Thanks,
--
Régis
> Do you have any other suggestion?
Can you call the EJB from the main thread in your client rather than
creating a new thread ?
Hi,
Thanks to Paul and Krao for their help.
I eventually made my client work. Here is how.
I assume that:
- you can already query the EJB from a servlet with the login
y817579/y817579
- the SSL key and trust are shared correctly between the client and the
server
The client needs to do a programmatic login (see WSLogin and WSSubject
http://publib.boulder.ibm.com/infocenter/wasinfo/v5r1//index.jsp%3Ftopic%3D/com.ibm.websphere.nd.doc/info/ae/ae/tsec_pacs.html)
Basically (try/catch removed), what I do is this:
Context initial = new InitialContext(env);
QuoteHome home =
(QuoteHome) PortableRemoteObject.narrow(
initial.lookup(jndiLookupName),
QuoteHome.class);
LoginContext lc = new LoginContext(
"ClientContainer", // I suppose WSLogin works too
new WSCallbackHandlerImpl(
(String) env.get(Context.SECURITY_PRINCIPAL),
(String) env.get(Context.SECURITY_CREDENTIALS)
));
lc.login();
quote = home.create();
WSSubject.doAs(subject, new java.security.PrivilegedAction() {
public Object run() {
Quotation q = quote.get();
System.out.println(q.getQuote());
if (q.getAuthor() != null && q.getAuthor().length() > 0) {
System.out.println("\t-- " + q.getAuthor());
}
}
});
The program is run with the arguments
-Djava.naming.provider.url=iiop://myserver
-Djava.naming.security.principal=y817579
-Djava.naming.security.credentials=y817579
At this point, you get the error message I described in my original
post.
Now, for the client to work, you need to define 2 properties file
-Dcom.ibm.CORBA.ConfigURL="C:\Program Files\IBM\WebSphere
Studio\Application
Developer\v5.1.2\runtimes\base_v5\properties\sas.client.props"
-Djava.security.auth.login.config="C:\Program Files\IBM\WebSphere
Studio\Application
Developer\v5.1.2\runtimes\base_v5\properties\wsjaas_client.conf"
In sas.client.propos, define
# RMI/IIOP user identity
and
com.ibm.CORBA.loginSource=none
hope this helps,
--
Régis
# RMI/IIOP user identity