[jboss-user] [Security & JAAS/JBoss] - Re: combination of JAAS

eivind@kadme.com do-not-reply at jboss.com
Fri Mar 14 21:16:46 EDT 2008


Hi!

I was asked by a response to my blog post (http://roneiv.wordpress.com/2008/02/19/perform-a-jaas-programmatic-login-in-jboss-try-to-solve-the-empty-remote-user-problem/)  to comment and maybe help on this issue.

I'm no expert on these matters, but I've managed to use the WebAuthentication BOTH from servlet context and from a handler to login a user to the application. And the user is properly set also in web container, so both externalContext.getRemoteUser() AND externalContext.getUserPrincipal().toString() return the logged on username.

Zilbi, it is my understanding that you have managed to log on to your application whith basic form-logon, using j_security_check etc. That's nice, because we then know that your login-config and ds works. Still, I will provide an example of the login-config I use, just in case it matters ;) This one uses a database with a user table, but the groups are static:


  | <application-policy name = "myApplication">
  |       <authentication>
  |       <login-module code = "org.jboss.security.auth.spi.DatabaseServerLoginModule" flag = "required">
  | 		<module-option name = "dsJndiName">java:/myDatasource-ds</module-option>  
  | 		<module-option name = "principalsQuery">Select password from user_table where user_name =? AND active = 'true'</module-option>
  | 		<module-option name = "rolesQuery">Select 'user', 'Roles', 'RoleGroups' from user_table where user_name =?</module-option>
  | 		<module-option name ="hashAlgorithm">md5</module-option>
  | 		<module-option name="hashEncoding">hex</module-option>
  | 		<module-option name="debug">false</module-option>
  |      </login-module>
  | 	 <login-module code="org.jboss.security.ClientLoginModule" flag="required" />
  | 	 </authentication>
  |  </application-policy>
  | 

The first thing to try is that the WebAuthentication class works as it should.
Create a LoginHandler or something similar, with a method login() and two helper-methods getRemoteUser and getUserPrincipal. Something like this:


  | public class LoginHandler
  | {
  |  
  | public String login()
  | {
  | 		WebAuthentication webAuthentication = new WebAuthentication();
  | 		
  | 		String hardcodedUserName = "zilbi at jboss.com";
  | 		String hardcodedPassword = "zilbi123";
  | 		
  | 		if (webAuthentication.login(hardcodedUserName, hardcodedPassword))
  | 		{
  | 		   System.out.println("Logged in successfully");;
  | 		
  | 			log.debug("userPrincipal: " + getUserPrincipal());
  | 			log.debug("remoteUser: " + getRemoteUser());
  | 		}
  | 		else
  | 		{
  | 			log.debug("Login failed");
  | 		}
  | 	
  | 		return "";
  | }
  | public String getUserPrincipal()
  | {
  | 		FacesContext context = FacesContext.getCurrentInstance();
  | 		ExternalContext externalContext = context.getExternalContext();
  | 		return externalContext.getUserPrincipal() != null ? externalContext.getUserPrincipal().toString() : "null";
  | }
  | 
  | public String getRemoteUser() 
  | {
  | 		FacesContext context = FacesContext.getCurrentInstance();
  | 		ExternalContext externalContext = context.getExternalContext();
  | 		String remoteUser = externalContext.getRemoteUser();
  | 		return remoteUser;
  | }
  | 
  | }
  | 

We basically hardcode the username/password, and just test if we get login to work. You should of course change these values to something that matches your login domain. Then create a simple jsp, but don't put it inside your protected folder. I see from you web.xml that you protect everything under /protected/*. Create it one level up so that you can access it without being asked to log in.

In this jsp you will have a stupid commandButton, as well as two outputs that displays the remoteUser and userPrincipal:


  | <f:view >
  | 	<t:document>
  | 	<t:documentHead>
  | 	   <f:loadBundle basename="MessageResources" var="messages" />
  | 	</t:documentHead>
  | 
  | 	<f:verbatim>
  | 		<body>
  | 	</f:verbatim>
  | 	<h:form>
  | 		<h:panelGrid>
  | 			<h:commandButton value="Login" action="#{loginHandler.login}"></h:commandButton>
  | 			<h:outputText value="User Principal: #{loginHandler.userPrincipal}"></h:outputText>	
  | 			<h:outputText value="Remote User: #{loginHandler.remoteUser}"></h:outputText>	
  | 		</h:panelGrid>
  | 	</h:form>
  | 	<f:verbatim>
  | 		</body> 
  | 	</f:verbatim>
  | 	</t:document>
  | </f:view>
  | 

Now, launch your application by going to this page. You will see that userPrincipal shows "null" and remoteUser is empty. Press the Login button. When the page reloads it should display your username in both outputTexts. If you check your log or console it should say "Logged in successfully." The user is now properly set in the web container. Do you get this to work? Also, if you now try to change the url to go to one of your protected pages, you should not be redirected to any login.jsp, but the page should display properly - because you are already logged on.

Then, to do the logon from a servlet there's really not a big difference. I set up my web.xml to use a FORM-based logon, like this:


  | <login-config>
  |     <auth-method>FORM</auth-method>
  |     <form-login-config>
  |      <form-login-page>/login.faces</form-login-page>
  |      <form-error-page>/loginFailed.faces</form-error-page>
  |     </form-login-config>
  |    </login-config>
  | 

I also register my LoginServlet in web.xml like this:

  | <servlet>
  |     <servlet-name>LoginServlet</servlet-name>
  | 	<servlet-class>com.test.servlet.LoginServlet</servlet-class>
  |   </servlet>
  |   
  |   <servlet-mapping>
  |     <servlet-name>LoginServlet</servlet-name>
  |     <url-pattern>/LoginServlet</url-pattern>
  |   </servlet-mapping>
  | 

My login.jsp is 99% the same as when using j_security_check, we just point the action to the LoginServlet instead:

  | <form method="POST" name="loginform" action="${pageContext.request.contextPath}/LoginServlet">
  | 	<table style="vertical-align: middle;">
  | 	<tr>
  | 		<td>Username:</td><td><input type="text" name="j_username"/></td>
  | 	</tr>
  | 	<tr>
  | 		<td>Password:</td><td><input type="password" name="j_password"/></td>
  | 	</tr>
  | 	<tr>
  | 		<td><input type="submit" value="Login" /></td>
  | 	</tr>
  | 	</table>
  | </form>
  | 
  | 

My LoginServlet uses the parameters that was originally passed to the j_security_check. Also, if we successfully log on, we get the "Referer" from the request to redirect to the page that originally was the target for the user. I did not include the code that handles if the logon failed here:

  | public class LoginServlet extends HttpServlet
  | {
  | 	@Override
  | 	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
  | 			throws ServletException, IOException
  | 	{
  | 		// TODO Auto-generated method stub
  | 		doPost(req, resp);
  | 		
  | 	}
  | 	
  | 	@Override
  | 	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
  | 			throws ServletException, IOException
  | 	{
  | 		String user = req.getParameter("j_username");
  | 		String pass = req.getParameter("j_password");
  | 		WebAuthentication webAuthentication = new WebAuthentication();
  | 		if(	webAuthentication.login(user, pass))
  | 		{	
  | 			String redirectUrl = "";
  | 			String referer = req.getHeader("Referer");
  | 			resp.sendRedirect(redirectUrl);
  | 			return;
  | 		}
  | 		else
  | 		{
  | 			System.out.println("Login attempt failed " + user);
  | 			...
  | 			Handle incorrect logon, go back to login page etc
  | 			...
  | 		}
  | 	}
  | }
  | 

So, to test this, start your application by pointing directly to some page that is protected. Your login.jsp should be presented, and when you press Login the servlet uses the credentials you passed in the forms, authenticates and redirect you to the page. For debug reasons you could add the same outputTexts here on this page (remoteUser and userPrincipal), and they SHOULD show the user you logged in with now. 

Hope that this might help you, but as I said, I'm no expert on this. And I don't know the effect of the two options you include in your login-config, if this could cause some bad behaviour or not:
anonymous wrote : 
  | <module-option name="restore-login-identity">true</module-option>
  | 				<module-option name="multi-threaded">true</module-option>

A good tip is to start with a minimal configuration till you get it working, and then slowly building it up to go where you want. :)

View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4136856#4136856

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4136856



More information about the jboss-user mailing list