I´m tying to add two servlets to an embedded tomcat. In this scenario one of the servlets should be "protected" by basic authentication. I want to add the security constraints via code only. Regarding to this Link it shouldn´t be to hard.
I build a test scenario:
Project: EmbeddedTomcatTest
-Source Packages
--tomcat.test
---ServletOne.java
---ServletTwo.java
---StartEmbeddedTomcat.java (contains main method)
-Test Packages
-Other Sources
--src/main/resources
---Tomcat-users.xml
-Project Files
--pom.xml
The dependencies of my pom looks like:
<dependencies>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>8.5.4</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
So far I added an embedded tomcat with two servlets which are accessible via different url patterns, which works fine.
public class StartEmbeddedTomcat {
private static final String AUTH_ROLE = "test";
public static void main(String[] args) throws LifecycleException {
Tomcat tomcat = new Tomcat();
tomcat.setPort(8080);
// adding a context
Context ctx = tomcat.addContext("/", new File(".").getAbsolutePath());
// Login Config
LoginConfig config = new LoginConfig();
config.setAuthMethod("BASIC");
// adding constraint with role "test"
SecurityConstraint constraint = new SecurityConstraint();
constraint.addAuthRole(AUTH_ROLE);
// add constraint to a collection with pattern /second
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/second");
constraint.addCollection(collection);
ctx.setLoginConfig(config);
// does the context need a auth role too?
ctx.addSecurityRole(AUTH_ROLE);
ctx.addConstraint(constraint);
// add servlet with pattenr /first and /second
Tomcat.addServlet(ctx, "one", new ServletOne());
ctx.addServletMapping("/first", "one");
Tomcat.addServlet(ctx, "two", new ServletTwo());
ctx.addServletMapping("/second", "two");
// add tomcat users to realm
String path = "tomcat-users.xml";
URL uri = ServletOne.class.getClassLoader().getResource(path);
MemoryRealm realm = new MemoryRealm();
realm.setPathname(uri.toString());
tomcat.getEngine().setRealm(realm);
tomcat.start();
tomcat.getServer().await();
}
}
The tomcat-users.xml
isn´t very special.
<tomcat-users>
<role rolename="manager-gui"/>
<role rolename="test"/>
<user name="admin" password="" roles="manager-gui"/>
<user name="test" password="test" roles="test"/>
</tomcat-users>
I think the code of the servlets is not important since they just response "Im servlet one" or "Im servlet two".
In my opinion the whole application or at least every request onto /second
should be protected. What did I do wrong? Is there something more I´ve to do?
----edit---
Today I found this question of stack overflow. I added noauthCTX.setAltDDName("Path\\to\\web.xml");
to my test scenario. The web.xml looks like:
<web-app>
<display-name>Test Service</display-name>
<servlet>
<servlet-name>ServletOne</servlet-name>
<servlet-class>tomcat.test.test.ServletOne</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ServletOne</servlet-name>
<url-pattern>/servletOne/*</url-pattern>
</servlet-mapping>
</web-app>
I thought my servlet one would be accessable via localhost:8080/servletOne/*
too. It isn´t.. actually I´m very confused. I hope someone can help me..