• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Not getting <form-error-page> using <auth-method>FORM</auth-method>

 
Ranch Hand
Posts: 71
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi all,

I am testing form authentification with a very simple app that just prints out a message if you authenticate. I am using MySQL as a database Realm. I define 2 user roles in my web.xml file and authorize them for access. When I run with the 2 roles in the web.xml file, all works fine. If I enter a bad username or password I get my <form-error-page> as expected. However, if I try to remove (comment out) one of the roles from web.xml, then try to use that role to login, instead of my <form-error-page> I get a Tomcat HTTP status 403 page, which is an access error, but I then navigate back to the login page and enter a valid credential, it too is rejected with the same Tomcat error page.

Here is my application context.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<Context path="/ch17admin">

<!-- The following specifies a JDBC Realm connecting to the murach
database using the root and admin login. Then it uses the murach
database columns from the UserPass and UserRole tables -->

<Realm className="org.apache.catalina.realm.JDBCRealm" debug="99"
driverName="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/murach"
connectionName="root" connectionPassword="sesame"
userTable="UserPass" userNameCol="Username" userCredCol="Password"
userRoleTable="UserRole" roleNameCol="Rolename" />

</Context>

Here is my application web.xml file:

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">

<!-- Define two security roles -->
<security-role>
<description>customer service employees</description>
<role-name>service</role-name>
</security-role>
<security-role>
<description>system administrator</description>
<role-name>programmer</role-name>
</security-role>

<!-- Restrict access to all files in the /admin folder -->
<security-constraint>
<web-resource-collection>
<web-resource-name>Protected Area</web-resource-name>
<url-pattern>/admin/*</url-pattern>
</web-resource-collection>
<!-- Authorize the programmer and service roles -->
<auth-constraint>
<role-name>service</role-name>
<!--<role-name>programmer</role-name> -->
</auth-constraint>
</security-constraint>

<!-- Use form-based authentication specifying the login and error forms -->
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/admin/login.html</form-login-page>
<form-error-page>/admin/login_error.html</form-error-page>
</form-login-config>
</login-config>

<!-- Use basic authentication -->
<!--
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>Admin Login</realm-name>
</login-config>
-->
<session-config>
<session-timeout>30</session-timeout>
</session-config>

<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

My login.html file:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Murach's Java Servlets and JSP</title>
</head>

<body>
<h1>Admin Login Form</h1>
<p>Please enter your username and password to continue.</p>
<table cellspacing="5" border="0">
<form action="j_security_check" method="get">
<tr>
<td align="right">Username</td>
<td><input type="text" name="j_username"></td>
</tr>
<tr>
<td align="right">Password</td>
<td><input type="password" name="j_password"></td>
</tr>
<tr>
<td><input type="submit" value="Login"></td>
</tr>
</form>
</table>
</body>
</html>

My login_error.html file:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<html>
<head>
<title>Murach's Java Servlets and JSP</title>
</head>

<body>

<h1>Admin Login Form - Error</h1>
<p>You did not log in successfully.</p>
<p>Please check your username and password and try again.</p>
<p>If that doesn't work, you may need to <br>
implement the JDBC realm as described in chapter 17.</p>

<table cellspacing="5" border="0">
<form action="j_security_check" method="get">
<tr>
<td align="right">Username</td>
<td><input type="text" name="j_username"></td>
</tr>
<tr>
<td align="right">Password</td>
<td><input type="password" name="j_password"></td>
</tr>
<tr>
<td><input type="submit" value="Login"></td>
</tr>
</form>
</table>
</body>
</html>

As I said, when both roles are in the web.xml file and I enter a bad credential, I get my login_error.html file, but if I remove a role from the web.xml, say "programmer", and then try to log in with it I get a Tomcat HTTP status 403 page.

Anyone know the issue?
Thanks in advance
Mike

 
Saloon Keeper
Posts: 27762
196
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm not clear on what you are trying to do.

Roles are not something that are dynamically added or removed from the security system, so normally what you're describing isn't a problem.

I did get the impression that maybe you think that user's only have one role each, and that is not true. Each user can have zero or more roles defined for him/her/it/that/whatever.
 
Mike Tabak
Ranch Hand
Posts: 71
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I know users can have more than one role. What I am saying is when I remove the programmer role from the web.xml file so it is no longer authorized to access the resources in /admin/ I would expect that the html page defined in the <form-error-page> tag would be displayed, but it is not. I get the Tomcat 403 page. If I leave the programmer role in, but use a bad password then I do get the html page defined in the <form-error-page> tag. I don't know why removing the programmer role from the web.xml and then trying to log in using that role does not also give the html page defined by the <form-error-page> tag.

Thanks
Mike
 
Tim Holloway
Saloon Keeper
Posts: 27762
196
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
OK. Have patience, I'm working my way backwards here, because I'm still trying to map your terminology to mine. Specifically, "remove a role".

You do 2 primary role-related things in web.xml:

1. Define a role name (security-role elements)

2. Map a role or roles to one or more URL patterns.

If you define a role and don't map it, it doesn't really matter, but properly speaking, if you map a role and didn't define it, Tomcat should refuse to deploy the webapp because referenced information (the role) was not defined.

The WEB-INF/web.xml file is technically referred to as the "container-independent Deployment Descriptor". It pairs with the container-dependent Deployment Descriptor, which, for tomcat, is the webapp's Context definition. This DD is read as part of the process of deploying a webapp, digested, and used to build the webapp's run environment. In Tomcat, if you have the right settings, Tomcat may scan the WAR, detect changes in the web.xml, undeploy the current instance and deploy a new instance (which includes digesting the updated web.xml), but the process is a little "iffy", since there may be lint left over from the previous instance, not to mention work in progress. So only do hot updates if you're feeling brave. Otherwise use a control interface to stop the webapp, redeploy, and restart. Or restart Tomcat itself, which is the same net effect.

On a related matter, removing a user from a given role will not take effect immediately. The user's role set is captured when the user logs in and not updated for the duration of the session, regardless of changes to the backing store. This is partly because changing security rules while someone is in the middle of a secured operation could have unforeseen (and possibly unpleasant) side effects. So the user has to log out and back in again before the role changes are seen.
 
Mike Tabak
Ranch Hand
Posts: 71
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for the reply, don't mean to sound impatient, just trying to get across what I'm doing. I am defining a security role, as you can see, and I am mapping it to a URL pattern. When I 'remove' the role, I tried two things (both in the web.xml file), first I just removed the mapping to the URL: the <role-name>programmer</role-name> line under the <security-role> tag. That should have disabled the programmer role from logging in, which it did, but I no longer go the login_error.html page described with the <form-error-page>/admin/login_error.html</form-error-page> line under the <login-config> tag. I get Tomcat's 403 resource restricted page.
I then removed the definition of the role: the <role-name>programmer</role-name> under the <security-role> tag. I got the same results. Each time I made a change I stopped and re-started Tomcat. According to the book I am using (Murach's Java Servlets and JSPs, 2nd Ed.) if I remove the programmer role, I should get the <form-error-page>/admin/login_error.html</form-error-page> just as if I entered a bad password for this role, but this is not happening.


Hope that better conveys what I'm doing
Thanks
Mike
 
Tim Holloway
Saloon Keeper
Posts: 27762
196
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
OK. I think I understand better.

You cannot disable a user login just by removing a role from that user's identity. Like I said earlier, a user can have zero or more roles. There's no formal "disable user" in J2EE - they can either login or they cannot. They can login as long as the Realm will return a confirmation on an authenticate request (made by the login processor). That's normally a simple match on userid/password, but more ambitious authenticators can add match on "account enabled" as long as they have some sort of internal arrangement on what enables an account.

If you remove a user from role "programmer", then URLs that require role "programmer" will be rejected, whether or not a login was forced, since the login (authentication) process is completely transparent to the downstream functions such as authorization (role-checking) and application logic. By the time the authorization is done, authentication is guaranteed and the users roles are all known.

Or perhaps it's better if I put it another way. You cannot forbid a login based on role. Role only controls what you're authorized to do after login. The container login is triggered not by which URL you are accessing, but by whether or not the URL is role-protected at all. If there are no roles, it's a public resource and no login is needed. If not, and the user isn't already logged in, a login is forced. This prevents the too-common exploit where people bypass login URLs and jump directly to the stuff behind the wall.
 
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
@Mike Tabak - I'm trying to do the same thing; did you find a way to replace Tomcat's 403 error page when an authenticated user isn't authorized for a constrained URL?
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
reply
    Bookmark Topic Watch Topic
  • New Topic