我们有一个在Tomcat 7.0.56上运行的简单web应用程序。现在我们想使用自己的身份验证领域。
public class SpecialAuth extends DataSourceRealm{
@Override
public Principal authenticate(String username, String credentials){
....
}
}
这是在war 内的/META-INF/context.xml中定义的
<Context>
<Realm className="some.package.SpecialAuth" dataSourceName="jdbc/MySQL" />
</Context>
SpecialAuth.class放在哪里
我们所期望的只是在我们的战争中拥有SpecialAuth.class,但随后我们在启动时遇到了愚蠢的异常
Caused by: java.lang.ClassNotFoundException: some.package.BackOfficeAuth
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
....
如果我们制作一个罐子,把它放入$TOMCAT/lib中,一切都很好。
但这不可能是解决方案!这意味着每次我处理这个类时,我都必须接触我的tomcat服务器,并且不能使用正常的部署。
如何在不一直接触tomcat的情况下使用内置身份验证机制ß
正如你所说,我不喜欢你的答案:)所以我所做的(我百分之百肯定你不喜欢它)是把这个领域设置在最肮脏的方式上,但现在我可以在一只有经验的tomcat上运行它了。经过163次验收测试,似乎没有任何问题。
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);
}
}
注:
- 反射.get()返回给定对象的(私有)实例变量的值
- 确保。。。()就像断言。。。但它抛出了Exception