Ahoj, vsichni,
na j2ee projektu se snazim zavest authentication + authorization/role
management, kde uzivatele a role jsou definovani v LDAPu. Protoze jde o
ciste enterprise projekt deployovany na JBoss AS, rozhodl jsem pouzit JAAS s
implementaci nabizenou JBoss serverem. Mym cilem je overeni uzivatele proti
LDAPu a nasledne pouzivani autorizacnich anotaci na EJB (@RollesAllowed()) a
webove vrstve (request.isUserInRole()).
Samotny login proti LDAPu s pomoci
org.jboss.security.auth.spi.LdapExtLoginModule se mi podaril celkem snadno.
Spravne se overi heslo a k uzivateli se dotahnou jeho role.
Co se mi ale ani za nic nedari, je Subject resp. Principal ziskany pri
loginu pouzit pri volani EJB metod a pristupu na webove stranky. Mam pocit,
ze misto toho, aby se mi Subject zpropagoval do EJBContext a ServletContext,
po loginu se proste zahodi.
Hledani na Googlu a v odpovidajici literature mi rika jen, ze by vsechno
melo fungovat spravne. Jenze nefunguje.
Dokazete mi, prosim, nekdo poradit, co delam spatne?
Diky,
C.
---------------------------------------------------------------------
Nastaveni login-config.xml:
<policy>
<application-policy name="localLdapPolicy">
<authentication>
<login-module code="org.jboss.security.auth.spi.LdapExtLoginModule"
flag="required" >
<module-option
name="java.naming.factory.initial">com.sun.jndi.ldap.LdapCtxFactory</module-option>
<module-option
name="java.naming.provider.url">ldap://localhost:10389</module-option>
<module-option
name="java.naming.security.authentication">simple</module-option>
<module-option name="bindDN">uid=admin,ou=system</module-option>
<module-option name="bindCredential">secret</module-option>
<module-option
name="baseCtxDN">ou=People,dc=example,dc=com</module-option>
<module-option name="baseFilter">(uid={0})</module-option>
<module-option
name="rolesCtxDN">ou=Roles,dc=example,dc=com</module-option>
<module-option name="roleFilter">(member={1})</module-option>
<module-option name="roleAttributeID">cn</module-option>
<module-option name="searchScope">ONELEVEL_SCOPE</module-option>
<module-option name="allowEmptyPasswords">false</module-option>
</login-module>
</authentication>
</application-policy>
</policy>
---------------------------------------------------------------------
descriptor xxx-ejb.jar/META-INF/jboss.xml :
<jboss>
<security-domain>localLdapPolicy</security-domain>
</jboss>
--------------------------------------------------------------------
descriptor xxx.war/WEB-INF/jboss-web.xml
<jboss-web>
<context-root>/LDAPLoginTestFacade</context-root>
<security-domain>java:/jaas/localLdapPolicy</security-domain>
</jboss-web>
---------------------------------------------------------------------
Servlet, ktery prijme jmeno/heslo zadane uzivatelem a pokusi se o login:
public class LoginServlet extends HttpServlet {
static final Logger logger =
Logger.getLogger(LoginServlet.class.getName());
@EJB(beanName = "LoginFacade")
LoginFacadeLocal loginFacade;
@EJB(beanName = "TestService")
TestServiceLocal testService;
protected void processRequest(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
try {
String user = request.getParameter("j_username");
String password = request.getParameter("j_password");
logger.info("logging user="+user+",pass="+password);
testEJBmethods(); // podle ocekavani vyhodi chybu (uzivatel neni
prihlasen)
loginFacade.login(user, password); // prihlaseni uspesne
probehne
testEJBmethods(); // podle ocekavani by melo projit, ale pada,
protoze Principal se neni asociovany s kontextem aplikace (viz. log)
logger.info("Session id="+request.getSession().getId());
if (request.isUserInRole("Admins")){
logger.info("User has Admins role");
}
if (request.getUserPrincipal() != null) {
logger.info("User logged in : "+
request.getUserPrincipal().getName());
}
response.sendRedirect(this.getServletContext().getContextPath()
+ "/index.jsp");
} catch (LoginException ex) {
logger.fatal("JAAS Login Failed: " + ex);
response.sendRedirect(this.getServletContext().getContextPath()
+ "/login.jsp");
}
}
private void testEJBmethods() {
try {
// bean method with @AllowedRoles("Operators")
testService.testOperators();
} catch (EJBAccessException ex) {
logger.error("testOperators access failed " + ex);
}
try {
// bean method with @AllowedRoles("Admins")
testService.testAdmins();
} catch (EJBAccessException ex) {
logger.error("testAdmin access failed " + ex);
}
}
}
---------------------------------------------------------------------
Beana provadejici autentizaci oproti LDAPu (ta probehne uspesne)
@Stateless
public class LoginFacade implements LoginFacadeLocal{
static Logger logger = Logger.getLogger(LoginFacade.class.getName());
@PermitAll
public void login(String user, String password) throws LoginException {
CallbackHandler handler = new UserPassHandler(user, password);
LoginContext lc = new LoginContext("localLdapPolicy", handler);
lc.login();
Subject subject = lc.getSubject();
if (subject != null) {
logger.info("Subject retrieved: " + subject);
}
}
}
---------------------------------------------------------------------
server.log:
2010-12-07 15:12:31,406 TRACE
[org.jboss.security.auth.login.XMLLoginConfigImpl] (http-0.0.0.0-8080-1)
Begin getAppConfigurationEntry(localLdapPolicy), size=11
2010-12-07 15:12:31,406 TRACE
[org.jboss.security.auth.login.XMLLoginConfigImpl] (http-0.0.0.0-8080-1) End
getAppConfigurationEntry(localLdapPolicy), authInfo=AppConfigurationEntry[]:
[0]
LoginModule Class: org.jboss.security.auth.spi.LdapExtLoginModule
ControlFlag: LoginModuleControlFlag: required
Options:
name=baseFilter, value=(uid={0})
name=java.naming.security.authentication, value=simple
name=java.naming.factory.initial, value=com.sun.jndi.ldap.LdapCtxFactory
name=allowEmptyPasswords, value=false
name=roleFilter, value=(member={1})
name=bindCredential, value=****
name=bindDN, value=uid=admin,ou=system
name=java.naming.provider.url, value=ldap://localhost:10389
name=rolesCtxDN, value=ou=Roles,dc=example,dc=com
name=baseCtxDN, value=ou=People,dc=example,dc=com
name=searchScope, value=ONELEVEL_SCOPE
name=roleAttributeID, value=cn
2010-12-07 15:12:31,422 TRACE
[org.jboss.security.auth.spi.LdapExtLoginModule] (http-0.0.0.0-8080-1)
initialize
2010-12-07 15:12:31,422 TRACE
[org.jboss.security.auth.spi.LdapExtLoginModule] (http-0.0.0.0-8080-1)
Security domain: localLdapPolicy
2010-12-07 15:12:31,422 TRACE
[org.jboss.security.auth.spi.LdapExtLoginModule] (http-0.0.0.0-8080-1) login
2010-12-07 15:12:31,453 TRACE
[org.jboss.security.auth.spi.LdapExtLoginModule] (http-0.0.0.0-8080-1)
Assign user to role Admins
2010-12-07 15:12:31,469 TRACE
[org.jboss.security.auth.spi.LdapExtLoginModule] (http-0.0.0.0-8080-1)
Assign user to role Operators
2010-12-07 15:12:31,469 TRACE
[org.jboss.security.auth.spi.LdapExtLoginModule] (http-0.0.0.0-8080-1) User
'admin' authenticated, loginOk=true
2010-12-07 15:12:31,469 TRACE
[org.jboss.security.auth.spi.LdapExtLoginModule] (http-0.0.0.0-8080-1)
commit, loginOk=true
2010-12-07 15:12:31,469 ERROR [STDERR] (http-0.0.0.0-8080-1) 7.12.2010
15:12:31 com.example.facade.LoginFacade login
INFO: Subject retrieved: Subject:
Principal: admin
Principal: Roles(members:Operators,Admins)
2010-12-07 15:12:31,469 ERROR [STDERR] (http-0.0.0.0-8080-1) 7.12.2010
15:12:31 com.example.facade.LoginFacade login
INFO: Principal retrieved: admin
2010-12-07 15:12:31,469 ERROR [STDERR] (http-0.0.0.0-8080-1) 7.12.2010
15:12:31 com.example.facade.LoginFacade login
INFO: Principal retrieved: Roles(members:Operators,Admins)
2010-12-07 15:12:31,469 DEBUG
[org.jboss.ejb3.proxy.handler.ProxyInvocationHandlerBase]
(http-0.0.0.0-8080-1) Couldn't handle invocation directly within
org.jboss.ejb3.proxy.handler.session.stateless.statelesslocalproxyinvocationhand...@393f3c:
Current invocation "public abstract void
com.example.facade.TestServiceLocal.testOperators()" is not eligible for
direct handling by
org.jboss.ejb3.proxy.handler.session.stateless.statelesslocalproxyinvocationhand...@393f3c
2010-12-07 15:12:31,469 DEBUG
[org.jboss.ejb3.common.registrar.plugin.mc.Ejb3McRegistrar]
(http-0.0.0.0-8080-1) Returning from name
"jboss.j2ee:ear=LDAPLoginTestFacade.ear,jar=LDAPLoginTestFacade-ejb.jar,name=TestService,service=EJB3":
jboss.j2ee:ear=LDAPLoginTestFacade.ear,jar=LDAPLoginTestFacade-ejb.jar,name=TestService,service=EJB3
2010-12-07 15:12:31,484 TRACE [org.jboss.security.SecurityRolesAssociation]
(http-0.0.0.0-8080-1) Setting threadlocal:{}
2010-12-07 15:12:31,484 TRACE
[org.jboss.security.plugins.authorization.JBossAuthorizationContext]
(http-0.0.0.0-8080-1) Control flag for
entry:org.jboss.security.authorization.config.AuthorizationModuleEntry{org.jboss.security.authorization.modules.DelegatingAuthorizationModule:{}REQUIRED}is:[REQUIRED]
2010-12-07 15:12:31,500 TRACE
[org.jboss.security.authorization.modules.ejb.EJBPolicyModuleDelegate]
(http-0.0.0.0-8080-1) method=public void
com.example.facade.TestService.testOperators(), interface=Local,
requiredRoles=Roles(Operators,)
2010-12-07 15:12:31,500 TRACE
[org.jboss.security.authorization.modules.ejb.EJBPolicyModuleDelegate]
(http-0.0.0.0-8080-1) Exception:Insufficient method permissions,
principal=null, ejbName=TestService, method=testOperators, interface=Local,
requiredRoles=Roles(Operators,), principalRoles=Roles()
2010-12-07 15:12:31,500 TRACE
[org.jboss.security.plugins.authorization.JBossAuthorizationContext]
(http-0.0.0.0-8080-1) REQUIRED failed for
Name=org.jboss.security.authorization.modules.DelegatingAuthorizationModule:subject=Subject:
Principal: anonymous
:role=Roles()
2010-12-07 15:12:31,500 TRACE
[org.jboss.security.plugins.authorization.JBossAuthorizationContext]
(http-0.0.0.0-8080-1) Error in authorize:
org.jboss.security.authorization.AuthorizationException: Authorization
Failed:
at
org.jboss.security.plugins.authorization.JBossAuthorizationContext.invokeAuthorize(JBossAuthorizationContext.java:263)
at
org.jboss.security.plugins.authorization.JBossAuthorizationContext.access$000(JBossAuthorizationContext.java:67)
at
org.jboss.security.plugins.authorization.JBossAuthorizationContext$1.run(JBossAuthorizationContext.java:152)
at java.security.AccessController.doPrivileged(Native Method)
at
org.jboss.security.plugins.authorization.JBossAuthorizationContext.authorize(JBossAuthorizationContext.java:148)
at
org.jboss.security.plugins.JBossAuthorizationManager.internalAuthorization(JBossAuthorizationManager.java:474)
at
org.jboss.security.plugins.JBossAuthorizationManager.authorize(JBossAuthorizationManager.java:124)
at
org.jboss.security.plugins.javaee.EJBAuthorizationHelper.authorize(EJBAuthorizationHelper.java:116)
at
org.jboss.ejb3.security.RoleBasedAuthorizationInterceptorv2.invoke(RoleBasedAuthorizationInterceptorv2.java:189)
at
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at
org.jboss.ejb3.security.Ejb3AuthenticationInterceptorv2.invoke(Ejb3AuthenticationInterceptorv2.java:186)
at
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at
org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:41)
at
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at
org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106)
at
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at
org.jboss.ejb3.BlockContainerShutdownInterceptor.invoke(BlockContainerShutdownInterceptor.java:67)
at
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at
org.jboss.aspects.currentinvocation.CurrentInvocationInterceptor.invoke(CurrentInvocationInterceptor.java:67)
at
org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at
org.jboss.ejb3.session.SessionSpecContainer.invoke(SessionSpecContainer.java:219)
at
org.jboss.ejb3.proxy.handler.ProxyInvocationHandlerBase.invoke(ProxyInvocationHandlerBase.java:261)
at
org.jboss.ejb3.proxy.handler.session.SessionSpecProxyInvocationHandlerBase.invoke(SessionSpecProxyInvocationHandlerBase.java:101)
at $Proxy135.testOperators(Unknown Source)
at com.example.LoginServlet.testEJBmethods(LoginServlet.java:84)
at com.example.LoginServlet.processRequest(LoginServlet.java:61)
...
2010-12-07 15:12:31,500 TRACE
[org.jboss.security.plugins.javaee.EJBAuthorizationHelper]
(http-0.0.0.0-8080-1) Error in authorization:
org.jboss.security.authorization.AuthorizationException: Authorization
Failed:
at
org.jboss.security.plugins.authorization.JBossAuthorizationContext.invokeAuthorize(JBossAuthorizationContext.java:263)
at
org.jboss.security.plugins.authorization.JBossAuthorizationContext.access$000(JBossAuthorizationContext.java:67)
at
org.jboss.security.plugins.authorization.JBossAuthorizationContext$1.run(JBossAuthorizationContext.java:152)
....
2010-12-07 15:12:31,500 TRACE
[org.jboss.security.audit.providers.LogAuditProvider] (http-0.0.0.0-8080-1)
[Error]Source=org.jboss.security.plugins.javaee.EJBAuthorizationHelper;Exception:=Authorization
Failed:
;Resource:=[org.jboss.security.authorization.resources.EJBResource:contextmap={policyregistration=org.jboss.security.plugins.jbosspolicyregistrat...@148b6d3}:method=public
void
com.example.facade.TestService.testOperators():ejbMethodInterface=Local:ejbName=TestService:ejbPrincipal=null:MethodRoles=Roles(Operators,):securityRoleReferences=null:callerSubject=Subject:
Principal: anonymous
:callerRunAs=null:callerRunAs=null:ejbRestrictionEnforcement=false:ejbVersion=null];policyregistration=org.jboss.security.plugins.jbosspolicyregistrat...@148b6d3
;
2010-12-07 15:12:31,500 ERROR [com.example.LoginServlet]
(http-0.0.0.0-8080-1) testOperators access failed
javax.ejb.EJBAccessException: Caller unauthorized
2010-12-07 15:12:31,625 DEBUG
[org.jboss.ejb3.proxy.handler.ProxyInvocationHandlerBase]
(http-0.0.0.0-8080-1) Couldn't handle invocation directly within
org.jboss.ejb3.proxy.handler.session.stateless.statelesslocalproxyinvocationhand...@393f3c:
Current invocation "public abstract void
com.example.facade.TestServiceLocal.testAdmins()" is not eligible for direct
handling by
org.jboss.ejb3.proxy.handler.session.stateless.statelesslocalproxyinvocationhand...@393f3c