views:

619

answers:

5

Hi there, I am trying to return a 401 error code from a webapp to trigger a basic authentication process, but tomcat is hijacking the response to display its status report page. Is there a way to prevent tomcat from doing this and let the error code go all the way to the browser?

UPDATE My mistake: I forgot the WWW-Authenticate header

+2  A: 

Unhappy with the default error pages that come with Tomcat ? You can define your own custom error pages in your web.xml file. In the example shown below, we define 2 web pages -- server_error.html and file_not_found.html -- which will be displayed when the server encounters an error 500 or an error 404 respectively.

<error-page>
    <error-code>500</error-code>
    <location>/server_error.html</location>
</error-page>
<error-page>
    <error-code>404</error-code>
    <location>/file_not_found.html</location>
</error-page>

You should bear in mind, however, that the order of the tags for the web.xml file is very important. If the order in your web.xml file is incorrect, Tomcat will output errors on startup

source: http://linux-sxs.org/internet_serving/c581.html

Peter
No, I don't want tomcat to display any error page whatsoever
Maurice Perry
@Maurice Perry, I believe what Peter is trying to tell you is that you should set up your error pages in the way he has mentioned. But in your error pages, you can do a redirect to an authentication page, where you ask the user to specify his credentials.
Shivasubramanian A
+2  A: 

The Tomcat error page might be happening because you're not including enough information for your browser to do what you want next. Although you're seeing a page it won't have a 200 Status Code. If you inspect the header you'll see a 401 in there. I suspect it's your browser that doesn't know what to do next.

You don't state in your question what you want the browser to do, but maybe you need to include extra information in the HTTP header of the 401 error message. You can override the default error messages by adding an error-page node to your web.xml file. The location can be a servlet or a JSP so you can provide some logic rather that just a static page.

<error-page>
    <error-code>401</error-code>
    <location>/my401.jsp</location>
</error-page>
banjollity
+3  A: 

Setting the response status to 401 will only tell the browser "forbidden", and tomcat will display the error page. It will not in itself trigger the authentication process.

To trigger auth, you need to add another header to the response:

httpResponse.setHeader("WWW-Authenticate", "Basic realm=\"MyApp\"");

where "MyApp" is the name of your desired HTTP auth realm. Add that header, and the browser will popup an auth dialog and retry the request.

You should be aware that tomcat will still have sent the error page along with the headers, it's just that the browser won't display it as long as the response contains the auth header.

skaffman
A: 

Why not use the login-config, security-constraint and security-role elements from web.xml for this? Little example:

<login-config>

  <auth-method>FORM</auth-method>

  <realm-name>Your-Name</realm-name>

  <form-login-config>

    <form-login-page>/login.jsp</form-login-page>

    <form-error-page>/error_login.xhtml</form-error-page>

  </form-login-config>

</login-config>


<security-constraint>

   <web-resource-collection>

      <web-resource-name>Some-Name</web-resource-name>

      <url-pattern>/path/to/directory/*</url-pattern>

   </web-resource-collection>

   <auth-constraint>

      <role-name>USER</role-name>

      <role-name>ADMIN</role-name>

   </auth-constraint>   

 </security-constraint>


 <security-role>

    <description>Role for all users</description>

    <role-name>USER</role-name>

 </security-role>


 <security-role>

    <description>role for all admins</description>

    <role-name>ADMIN</role-name>

 </security-role>

With that users who want to visit your /path/to/directory/ or any of it's sub-directories will need to login. Access will be only granted if the user has the role USER or ADMIN. You can set this even to the root directory so all users will have to login first..

seb
Basic authentication is a requirement. It's a long story...
Maurice Perry
A: 

The answers above are not 100% clear, so this is what helped me. I had a static 401.html page and experienced the same problem as the original poster. All I did was to change the page to a 401.jsp page and dump this right at the top:

<%  
 String realmName = "A nice name to show as the title of on the pop-up";  
 response.setHeader("WWW-Authenticate","Basic realm=\"" + realmName + "\"");  
 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);  
 %>  

The following post on coderanch.com served as guidance.

So in a nutshell, the pertinent section of web.xml looks like this:

<!-- Internal server error. -->
   <error-page>
    <error-code>500</error-code>
    <location>/errors/500.html</location>
   </error-page>

  <!-- Not found. --> 
  <error-page>
    <error-code>404</error-code>
    <location>/errors/404.html</location>
  </error-page>

  <!-- Unauthorized. -->
  <error-page>
    <error-code>401</error-code>
    <location>/errors/401.jsp</location>
  </error-page>

And 401.jsp looks like this:

<%  
 String realmName = "A nice name to show as the title of on the pop-up";  
 response.setHeader("WWW-Authenticate","Basic realm=\"" + realmName + "\"");  
 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);  
 %>  
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml"&gt;
<head>
<title>401 Unauthorized</title>
<meta name="description" content="The server has not found anything matching the Request-URI.">
<style type="text/css">
body {background-color:ffffff;background-image:url(http://);background-repeat:no-repeat;background-position:top left;background-attachment:fixed;}
h3{font-family:Arial;color:000000;}
p {font-family:Arial;font-size:14px;font-style:normal;font-weight:normal;color:000000;}
</style>
</head>
<body>
<h3>401 Unauthorized</h3>
<p>The request requires authentication.</p>
</body>
</html>
Nico de Wet