tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From André Warnier>
Subject Re: Basic Authentication Failed with multibyte username
Date Thu, 21 Jan 2010 23:35:32 GMT
To get back to the underlying issue :

Auth Gábor wrote:
> So... this is the real chaos... :)


> By the way, my users are not use HTML browsers, they are using JAX-WS in their 
> client program, and the JAX-WS sends authentication data in UTF-8 (like 
> Opera), because the default encoding is UTF-8 in the client JVM (and the 
> server too).

Basically, I would tend to say that if the server knows who the clients 
are and vice-versa, you should be free to use any encoding you want, 
with the limitation that what is exchanged on the wire conforms to HTTP 
(because there may be proxies on the way which are not so tolerant).

What the client is sending is already (in a way) conformant to HTTP, 
because it is base64 encoded and so, on the surface, it does not contain 
non-ascii characters.
And (I presume) you cannot change the code of the client, so it will 
continue to send these "invalid" headers with a UTF-8 value, base64-encoded.

But the problem is that the standard Tomcat code which decodes the Basic 
Authorization header does not work in the way you want, for these 
illegal headers.
And this code should preferably not be changed in a way which breaks the 
conformance with standard HTTP.
Because if you do that, then your Tomcat becomes useless for anything 
else than your special client.

An additional complication is that, if you want to use the embedded 
"container-managed" Tomcat authentication mechanisms, then you have to 
do something very early in the cycle, because that authentication takes 
place even before any servlet filter is invoked.

Up to Tomcat 5.5, you would have to do this in a Valve then, which has 
the inconvenient that it is Tomcat-specific.  (I think Tomcat 6 may give 
other options, maybe not Tomcat-specific.)

Or, you drop the container-managed security, and you use something like 
the SecurityFilter (, but read 
the homepage carefully first.

So, to be pragmatic, I would tend to go in the following direction :
- create a Valve which
- checks the User-Agent. If it does not match your special client, do 
nothing.  If it matches, then
- get the Authorization header. If there is none, do nothing
- else, decode its value properly into a Unicode string
- re-encode this string in a way that fits with standard HTTP.  For 
example, replace each character by a string like {xxxx}, where xxxx is 
the hex value of the Unicode codepoint of the character.
(That is always valid us-ascii, but check the maximum length).
- re-encode the result using base64
- replace the Authorization header value with this new string
- in your back-end authentication mechanism (I will suppose it is a 
database of userids/passwords), encode the userids/passwords the same 
way, and make this an alternate key

The embedded Tomcat authentication will then decode the new base64 
string, split it into userid:password, and use them to verify the 
credentials, which will match.

If you do not like a Valve, then use a front-end server like Apache, and 
do the transformation of the header there, before the request is passed 
to Tomcat.
Alternatively then, you could also do the user authentication at the 
Apache level, and just pass the user-id to Tomcat.
(being an Apache/mod_perl guy myself, I find this last option much 
easier, but YMMV).

And all that for a few Ö's and Á's and ß's....

Another option is to use a front-end Apache httpd server, which would 
modify the requests as follows :

(I presume that you have a way to identify requests coming from this 
particular client)(User-Agent header e.g.).

Create a filter at the Apache level, which detects your special client.
If it detects it, then it adds an additional header to the request

To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message