简体   繁体   中英

How to deliver Realm with the war with Tomcat?

we have a simple web application running on Tomcat 7.0.56. Now we want to use our own realm for authentication.

public class SpecialAuth extends DataSourceRealm{
    @Override
    public Principal authenticate(String username, String credentials){
        ....
    }
}

This is defined in the /META-INF/context.xml inside the war

<Context>
    <Realm className="some.package.SpecialAuth" dataSourceName="jdbc/MySQL" />
</Context>

Where to put the SpecialAuth.class?

What we expected was simply to have the SpecialAuth.class inside our war but then we're getting folling exception on startup

Caused by: java.lang.ClassNotFoundException: some.package.BackOfficeAuth
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    ....

If we make a jar, putting it into $TOMCAT/lib everything works fine.

But this CAN'T be the solution! That would mean every time I work on this class(es) I have to touch my tomcat server and can't use the normal deployment.

How can I use the build-in authentication mechanism without touching the tomcat all the timeß

As you said I don't like your answers :) So what I did (and I'm 100% sure that you don't like it) was to set the realm on the dirties possible way BUT now I can run it on a ontouched tomcat. After 163 acceptance tests nothing seems to break.

public final class ContextListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent event) {
        ServletContext servletContext = event.getServletContext();
        TomcatContextManipulator tomcat = new TomcatContextManipulator(servletContext);
        tomcat.applyRealm(new MyOwnRealm());
    }
}

.

public class TomcatContextManipulator {
    private static final String EXPEXCTED_TOMCAT_VERSION = "7.0.52.0";

    private ApplicationContextFacade servletContext;

    /**
     * @param servletContext must be of type {@link ApplicationContextFacade}
     */
    public TomcatContextManipulator(ServletContext servletContext) {
        checkTomcatVersion();

        ensureEquals(servletContext.getClass(), ApplicationContextFacade.class, "class of servletContext");
        this.servletContext = (ApplicationContextFacade) servletContext;
    }

    /**
     * checks if the correct version of tomcat is in use, throws {@link IllegalStateException} if not
     */
    private void checkTomcatVersion() {
        // we use several internal parts of tomcat (for example with reflection)
        // by doing this we bind ourself hardly to a explicit version
        ensureEquals(EXPEXCTED_TOMCAT_VERSION, ServerInfo.getServerNumber(), "Tomcat-Server-Version");
    }

    /**
     * overrides the existing realm with the given on
     */
    public void applyRealm(Realm realm) {
        ensureNotNull(realm, "realm");
        ApplicationContext applicationContext = (ApplicationContext) ReflectionUtil.get(servletContext, "context");
        StandardContext standardContext = (StandardContext) ReflectionUtil.get(applicationContext, "context");
        standardContext.setRealm(realm);
    }
}

Note:

  • Reflection.get() returns the value of the (private) instance variable of the given object
  • ensure...() is like assert... but it throws Exception

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM