We used JDBC Realm. For production environment, you would probably use LDAP Realm. But steps will be more or less same.
Before we continue, it will be good to have a quick understanding of JAAS: It is an API that consists of a set of Java packages designed for user authentication and authorization; and implements a Java version of the standard pluggable authentication framework. The keyword here is “pluggable” – i.e. it does a lot of standard security related work for you without making you write a lot of code.
Here are the steps for JAAS implementation on JBoss AS7.
- Create user and roles tables that JAAS is going to use. Note the password field is varchar(32). This is good enough to store MD5 encrypted password.
-- Table user CREATE TABLE IF NOT EXISTS `jaasProject`.`user` ( `id` INT NOT NULL AUTO_INCREMENT , `username` VARCHAR(45) NOT NULL , `password` VARCHAR(32) NOT NULL , PRIMARY KEY (`id`) ); -- Table user_role CREATE TABLE IF NOT EXISTS `jaasProject`.`user_role` ( `id` INT NOT NULL AUTO_INCREMENT , `role` VARCHAR(64) NOT NULL , `user_id` INT NOT NULL , PRIMARY KEY (`id`) , INDEX `fk_user_role_user1` (`user_id` ASC) , CONSTRAINT `fk_user_role_user1` FOREIGN KEY (`user_id` ) REFERENCES `jaasProject`.`user` (`id` ) ON DELETE NO ACTION ON UPDATE NO ACTION);
-
Add some data to these tables. This could be done directly through SQL script, with something like this:
INSERT INTO user VALUES ('admin.user',MD5('admin_user_secret') );But the issue we encountered is: password encrypted on JBoss server didn’t match inserted password. Therefore we used following JUnit to insert data. This worked well, since we could encrypt using MD5 and also match encoding (BASE64 in this case) on both sides. Also note, you will need JBoss security framework jar picketbox.4.0.x.FINAL.jar to use the Util class to encrypt password. You can get it from JBoss runtime. For Maven users, this is what you will need:
<dependency> <groupId>org.picketbox</groupId> <artifactId>picketbox</artifactId> <version>4.0.7.Final</version> </dependency>Sample JUnit to insert user data and roles.
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "/applicationContext-test.xml"}) public class UserTest { @Autowired protected UserService userService; @Rollback (false) @Test public void test_CreateUser() { User user = new User(); user.setUsername("admin.user"); user.setPassword(Util.createPasswordHash("MD5", Util.BASE64_ENCODING, null, null, "admin_user_secret");); List<UserRole> userRoles = new ArrayList<UserRole> (); // admin role UserRole adminRole = new UserRole(); adminRole.setUser(user); adminRole.setRole("admin"); userRoles.add(adminRole); // management role UserRole mgmtRole = new UserRole(); mgmtRole.setUser(user); mgmtRole.setRole("mgmt"); userRoles.add(mgmtRole); // create user user.setUserRoles(userRoles); userService.createUser(user); } } -
Now we have the user data and user roles in database, the next step is to setup on the server side. Go to installation directory for JBoss. That is: $JBOSS_HOME/standalone/configuration or $JBOSS_HOME/domain/servers/
/configuration. For standalone system, open standalone.xml file in $JBOSS_HOME/standalone/configuration. We assume, you have setup a datasource on server side, for eg. dsJaasProject. <subsystem xmlns="urn:jboss:domain:security:1.1"> <security-domains> ... <security-domain name="jaasProject" cache-type="default"> <authentication> <login-module code="Database" flag="required"> <module-option name="dsJndiName" value="java:jboss/datasources/dsJaasProject"/> <module-option name="principalsQuery" value="select password from user where username=?"/> <module-option name="rolesQuery" value="select role, 'Roles' from user_role ur inner join user u on ur.user_id = u.id where u.username =?"/> <module-option name="hashAlgorithm" value="MD5"/> <module-option name="hashEncoding" value="base64"/> <module-option name="unauthenticatedIdentity" value="guest"/> </login-module> </authentication> </security-domain> </security-domains> </subsystem>Save the standalone.xml and restart JBoss server.
-
The next step is on the application side. Need to define available roles, resource and role mapping, login page and error page.
In web.xml:<!-- Roles --> <security-role> <description>Administrators</description> <role-name>admin</role-name> </security-role> <security-role> <description>Management</description> <role-name>mgmt</role-name> </security-role> <!-- Resource / Role Mapping --> <security-constraint> <display-name>Admin Area</display-name> <web-resource-collection> <web-resource-name>admin_resources</web-resource-name> <url-pattern>/admin/*</url-pattern> <http-method>GET</http-method> <http-method>POST</http-method> </web-resource-collection> <auth-constraint> <description>For admin role only</description> <role-name>admin</role-name> </auth-constraint> <user-data-constraint> <transport-guarantee>NONE</transport-guarantee> </user-data-constraint> </security-constraint> <!-- Login Prompt --> <login-config><auth-method>FORM</auth-method> <form-login-config> <form-login-page>/login/login.xhtml</form-login-page> <form-error-page>/error.xhtml</form-error-page> </form-login-config> </login-config>
-
The next step is the connection between app and server. This is done via jboss-web.xml in your application. Create new file and place it in the same folder where web.xml is located. With the below definition, a JNDI lookup will be done for jaasProject in the server (which we defined earlier in standalone.xml).
<?xml version="1.0" encoding="UTF-8"?> <jboss-web> <security-domain>java:/jaas/jaasProject</security-domain> </jboss-web>With this, all resources defined in web.xml will be available only if authorized by the server (if the user has the roles that have access to the resource).
First, if not logged in, login page will be prompted. Note the login page:<form method="post" action="j_security_check"> <h:panelGrid id="panel" columns="2" border="1"> <h:outputLabel value="Username" /><input type="text" name="j_username" size="25" /> <h:outputLabel value="Password" /><input type="password" size="15" name="j_password" /> .... </h:panelGrid> </form>Note the form action (j_security_check), username name attribute (j_username) and password name attribute (j_password). This will delegate the authentication to j_security_check servlet. Once authenticated by server (as defined by jdbcRealm).
Second, if authenticated, server will validate for authorization, whether the role has access to the resources. If yes, the user will have access to the resources. If not, an error page will be displayed.
That’s it. If you get stuck or have a question, please leave us a comment and we will try to help.

Hi,
I followed your step:
When I put username and password in conrect: error page will visible.
And server log throw error:
11:41:19,902 ERROR [org.jboss.security.authentication.JBossCachedAuthenticationManager] (http--192.168.95.22-8080-1) Login failure: javax.security.auth.login.FailedLoginException: Password Incorrect/Password Required
at org.jboss.security.auth.spi.UsernamePasswordLoginModule.login(UsernamePasswordLoginModule.java:270) [picketbox-4.0.7.Final.jar:4.0.7.Final]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.7.0_05]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) [rt.jar:1.7.0_05]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.7.0_05]
at java.lang.reflect.Method.invoke(Method.java:601) [rt.jar:1.7.0_05]
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:784) [rt.jar:1.7.0_05]
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:203) [rt.jar:1.7.0_05]
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:698) [rt.jar:1.7.0_05]
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:696) [rt.jar:1.7.0_05]
at java.security.AccessController.doPrivileged(Native Method) [rt.jar:1.7.0_05]
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:695) [rt.jar:1.7.0_05]
at javax.security.auth.login.LoginContext.login(LoginContext.java:594) [rt.jar:1.7.0_05]
at org.jboss.security.authentication.JBossCachedAuthenticationManager.defaultLogin(JBossCachedAuthenticationManager.java:449) [picketbox-infinispan-4.0.7.Final.jar:4.0.7.Final]
at org.jboss.security.authentication.JBossCachedAuthenticationManager.proceedWithJaasLogin(JBossCachedAuthenticationManager.java:383) [picketbox-infinispan-4.0.7.Final.jar:4.0.7.Final]
at org.jboss.security.authentication.JBossCachedAuthenticationManager.authenticate(JBossCachedAuthenticationManager.java:371) [picketbox-infinispan-4.0.7.Final.jar:4.0.7.Final]
at org.jboss.security.authentication.JBossCachedAuthenticationManager.isValid(JBossCachedAuthenticationManager.java:160) [picketbox-infinispan-4.0.7.Final.jar:4.0.7.Final]
at org.jboss.as.web.security.JBossWebRealm.authenticate(JBossWebRealm.java:214) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final]
at org.apache.catalina.authenticator.FormAuthenticator.authenticate(FormAuthenticator.java:280) [jbossweb-7.0.13.Final.jar:]
................................
But when I login by user and password correctly, then click submit button
Server didn't throw error.
I just receive in my firefox:
The connection was reset
The connection to the server was reset while the page was loading.
The site could be temporarily unavailable or too busy. Try again in a few moments.
If you are unable to load any pages, check your computer's network
connection.
If your computer or network is protected by a firewall or proxy, make sure
that Firefox is permitted to access the Web.
//
Could you plz give me your advise?
Thanks,
I resolved it. Because I should access to file in admin folder to authenticate.
If someone would like to have source for reference, please mail for me: jamesleviet@gmail.com
How to do the same with LoginContext , i mean programatically in java not in jsp
How can I pass three parameters (1) userName (2) password (3) domain from the login.xhtml? I noticed that the out of the box implementation of JDBC Realm provided by JBoss passes only username and password via CallbackHandler which are Namecall and PasswordCall. My problem is to pass the third parameter to the handle() method of my custom JAAS loginModule.
Once delegated to j_security_check, it's up to the specific JEE implementation of the app server how to handle this. Using a Custom Login Module might be one of the options.
Latest blog post: On Building Software Products
In my application, we use JSF & AJAX component to pull information based on user id and show it as drop down field besides "password". So, we have three fields on the login page. (1) user name (2) password (3) domain name. The reason is that the user has one user id but different roles based on the domain.
In this situation, is it possible to use j_security_check? The examples, I have seen so far use only two fields (1) user name and (2) password.
Tnx! Now it really clear for me.
@eskelevra I think making use of JAAS lets you not write the code behind the login button. If you read #5 in the post, you will notice that the action of the JSF page is j_security_check and not some action in your managed bean. So the action is handled by JAAS. Think of this way: your app has resources that either are secure or not. You will define the secure resources in web.xml. And when those resources are being accessed by someone, the login will be prompted. If authenticated, the user will get to that page, else, to the error page. Does it make sense?
how to configure java class that will handle login button?
There have been some issues reported with JBoss 7.1 with IE and FireFox (related to session / cookies). Try upgrading to 7.1.1. And also try Chrome to check if the problem persists.
SANJAY I got it working but now I get this error:::
HTTP Status 408 - The time allowed for the login process has been exceeded. If you wish to continue you must either click back twice and re-click the link you requested or close and re-open your browser
Im working with JbossAS 7.1 Brontes...
great tut..can you publish a link to the source code of all the files to have a better idea.. I'm kind of new to jaas and Jboss.. thanks