Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [jetty-users] Need Help Configuring A Security Handler for Embedded Jetty

Here is what the setup method for my tests looks like:

private static HashLoginService loginService;

private final static int port = 8089;

@BeforeClass

public static void setUpBeforeClass() throws Exception {

server = new Server(port);

ClassList classList = ClassList.setServerDefault(server);

// uncommenting this line will avoid the error but require us to specify all the configuration from jetty-web.xml by hand.

// boolean removed = classList.remove("org.eclipse.jetty.webapp.JettyWebXmlConfiguration");

classList.addAfter("org.eclipse.jetty.webapp.FragmentConfiguration", "org.eclipse.jetty.plus.webapp.EnvConfiguration", "org.eclipse.jetty.plus.webapp.PlusConfiguration");

WebAppContext context = new WebAppContext("eyerep-data", "/eyerep-data");

context.setDescriptor("src/main/webapp/WEB-INF/web.xml");

context.setResourceBase("src/main/webapp");

//we want a custom configuration for the tests so we need to supply an override descriptor

context.setOverrideDescriptors(Arrays.asList("src/test/resources/override-web.xml"));

// Creating the LoginService for the realm

loginService = new HashLoginService("EyeRep");

// Setting the realm configuration there the users, passwords and roles reside

loginService.setConfig("src/test/resources/realm.properties");

context.getSecurityHandler().setLoginService(loginService);

context.getSecurityHandler().setAuthenticator(new BasicAuthenticator());

BasicDataSource ds = null;

    ds = new BasicDataSource();

    ds.setUrl("jdbc:h2:mem:myDB;create=true;MODE=MSSQLServer;DATABASE_TO_UPPER=FALSE;");

org.eclipse.jetty.plus.jndi.Resource mydatasource = new org.eclipse.jetty.plus.jndi.Resource(null, "jdbc/NavDS",ds);


server.setHandler(context);

server.start();


}



If I run the test with that code, it will end up overriding my custom security handler with the values from jetty-web.xml when server.start() is called. I can work around it by removing org.eclipse.jetty.webapp.JettyWebXmlConfiguration from the class list, but then I have to specify everything that would normally be handled by jetty-web.xml by hand. I'm trying to keep my test configuration as close to the production config as possible and only override the things that need to be different for the test environment.



On Fri, Dec 10, 2021 at 7:02 PM Jan Bartel <janb@xxxxxxxxxxx> wrote:
Patrick,

You'd need to provide the non-working code. In the absence of that, I've whipped up a working example that might help you:


public class OneWebApp
{
    public static Server createServer(int port) throws IOException
    {
        // Create a basic jetty server object that will listen on port 8080.
        // Note that if you set this to port 0 then a randomly available port
        // will be assigned that you can either look in the logs for the port,
        // or programmatically obtain it for use in test cases.
        Server server = new Server(port);

        // The WebAppContext is the entity that controls the environment in
        // which a web application lives and breathes. In this example the
        // context path is being set to "/" so it is suitable for serving root
        // context requests and then we see it setting the location of the war.
        // A whole host of other configurations are available, ranging from
        // configuring to support annotation scanning in the webapp (through
        // PlusConfiguration) to choosing where the webapp will unpack itself.
        WebAppContext webapp = new WebAppContext();
        webapp.setContextPath("/");
        Path warFile = JettyDemos.find("demo-async-rest/demo-async-rest-webapp/target/demo-async-rest-webapp-@VER@.war");
        webapp.setWar(warFile.toString());

        String realmResourceName = "etc/realm.properties";
        ClassLoader classLoader = SecuredHelloHandler.class.getClassLoader();
        URL realmProps = classLoader.getResource(realmResourceName);
        if (realmProps == null)
            throw new FileNotFoundException("Unable to find " + realmResourceName);

        LoginService loginService = new HashLoginService("XX",
            realmProps.toExternalForm());

        webapp.getSecurityHandler().setLoginService(loginService);

        // A WebAppContext is a ContextHandler as well so it needs to be set to
        // the server so it is aware of where to send the appropriate requests.
        server.setHandler(webapp);
        return server;
    }

    public static void main(String[] args) throws Exception
    {
        int port = ExampleUtil.getPort(args, "jetty.http.port", 8080);
        Server server = createServer(port);

        Configurations.setServerDefault(server);

        // Start things up!
        server.start();

        server.dumpStdErr();

        // The use of server.join() the will make the current thread join and
        // wait until the server is done executing.
        server.join();
    }


On Sat, 11 Dec 2021 at 04:34, Patrick Buchheit <pbtura@xxxxxxxxx> wrote:
I posted this question on StackOverflow ( https://stackoverflow.com/questions/70278074/override-login-service-for-embedded-jetty ) but I'm hoping someone here can help as well. I'm trying to do some integration testing on a jetty application with basic authentication. I'm using a jetty-web.xml file to configure the security handler like this:

<Configure id="eyerep-data" class="org.eclipse.jetty.webapp.WebAppContext">

<Set name="contextPath">/eyerep-data</Set>

<Set name="war"><SystemProperty name="jetty.base" default="./webapps" />/eyerep-data/eyerep-data.war</Set>

<Get name="securityHandler">

    <Set name="loginService">

      <New class="org.eclipse.jetty.security.HashLoginService">

            <Set name="name">EyeRep</Set>

            <Set name="config"><SystemProperty name="jetty.home" default="."/>/etc/realm.properties</Set>

      </New>

    </Set>

  </Get>

</Configure>



That works for production, but for testing, I'm using an embedded jetty server so I need to use a different config path for the login service.


The problem I'm running into is that there doesn't seem to be any way to override just the config path. if I try to do something like: 


WebAppContext context = new WebAppContext();

loginService = ((HashLoginService)context.getSecurityHandler().getLoginService());

loginService.setConfig("src/test/resources/realm.properties");


I found that there is no point where that code can succeed. If I run it before calling 'server.start()' the login service has not been initialized yet and I get an NPE. If I run it after the call to 'server.start()', it is too late. The server will already have tried and failed to setup the user store using the invalid config path.


I'm at a bit of a loss here. I don't see anything equivalent to context.setOverrideDescriptors() for jetty-web.xml. Is there any way to do this without completely replacing the work done by jetty-web.xml with manual code?


_______________________________________________
jetty-users mailing list
jetty-users@xxxxxxxxxxx
To unsubscribe from this list, visit https://www.eclipse.org/mailman/listinfo/jetty-users


--
Jan Bartel <janb@xxxxxxxxxxx>
www.webtide.com
Expert assistance from the creators of Jetty and CometD

_______________________________________________
jetty-users mailing list
jetty-users@xxxxxxxxxxx
To unsubscribe from this list, visit https://www.eclipse.org/mailman/listinfo/jetty-users

Back to the top