Getting a value from HttpServletRequest.getRemoteUser() in Tomcat without modifying application
Solution 1
Here is a proof of concept Valve
implementation which does it:
import java.io.IOException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.realm.GenericPrincipal;
import org.apache.catalina.valves.ValveBase;
public class RemoteUserValve extends ValveBase {
public RemoteUserValve() {
}
@Override
public void invoke(final Request request, final Response response)
throws IOException, ServletException {
final String username = "myUser";
final String credentials = "credentials";
final List<String> roles = new ArrayList<String>();
// Tomcat 7 version
final Principal principal = new GenericPrincipal(username,
credentials, roles);
// Tomcat 6 version:
// final Principal principal = new GenericPrincipal(null,
// username, credentials, roles);
request.setUserPrincipal(principal);
getNext().invoke(request, response);
}
}
(Tested with Tomcat 7.0.21.)
Compile it, put it inside a jar and copy the jar to the apache-tomcat-7.0.21/lib
folder. You need to modify the server.xml
:
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Valve className="remoteuservalve.RemoteUserValve" />
...
I suppose it works inside the Engine
and Context
containers too.
More information:
Solution 2
Use a local, file-based realm for testing. Check your conf/tomcat-users.xml
and create roles and users for your application and enable the security constraints in your web.xml. There are good examples in the tomcat-users.xml
.
Mark
Updated on June 04, 2022Comments
-
Mark almost 2 years
(Using Java 6 and Tomcat 6.)
Is there a way for me to get
HttpServletRequest.getRemoteUser()
to return a value in my development environment (i.e. localhost) without needing to modify my application's web.xml file?The reason I ask is that the authentication implementation when the app is deployed to a remote environment is handled by a web server and plugged-in tool. Running locally I obviously do not have the plugged-in tool or a separate web server; I just have Tomcat 6. I am trying to avoid adding code to my application merely to support development on my localhost.
I am hoping there is a modification I can make to the context.xml or server.xml files that will let me set the remote user ID or that will try to pull it from a HTTP header or something.
-
Mark over 12 yearsYes, I have noticed the
tomcat-users.xml
file and know about adding security constraints within my app's web.xml, but I am asking if there is a way to achieve something similar without modifying actual/real/destined-for-production code; I would be happier modifying just my local server configuration. -
Mark over 12 yearsThanks for all the information! I created a class like you describe, JAR'd it up and updated the
server.xml
file. I had to make one change because I am running Tomcat v6.0.20: theGenericPrincipal
signature requires a realm so I addedfinal Realm realm = request.getContext().getRealm();
. However, it doesn't seem to be having an effect. I've tried updating thecontext.xml
file, too, but again it produced no result. The request's principal and user ID are bothnull
when they reach my application code. Did you perhaps do anything else? -
palacsint over 12 yearsI just passed
null
as realm, and it works for me with Tomcat 6.0.20. (See my modifications in the answer.) Are there any exception in your logs? -
Mark over 12 yearsThanks very much for the help with all this. It turns out I had your valve implemented correctly all along. The reason it didn't work was because I wasn't savvy to the significance of setting the
catalina.base
JVM property on server start-up. Once I altered theserver.xml
at that location it all worked perfectly. Thanks again! -
Edward about 11 yearsHi, palacsint Could you show more details of deployed the remote user through xml file... Thanks!
-
palacsint about 11 years@Edward: I'm sorry, I don't have time now for a complete answer. I guess you should ask it as a new question. Drop me a link and I'll check on the weekend if nobody answer it.
-
Edward about 11 yearsThank you very much! palacsint, I have posted here, Thanks ...
-
Adam Michalik over 7 yearsActually you can forget the
GenericPrincipal
and implement the simplePrincipal
interface yourself or rip offBasicUserPrincipal
from Apache HttpClient.