apache / shiro

Apache Shiro
https://shiro.apache.org/
Apache License 2.0
4.32k stars 2.31k forks source link

Tomcat 10.1 and Shiro 2.x giving javax.servlet Error #1028

Closed Divyanshgarg closed 1 year ago

Divyanshgarg commented 1 year ago

Search before asking

Question

Hi,

I am facing an issue with NoClassDefFoundError when using shiro 2.x with tomcat 10.1.11 on java 17.

I have gone through existing issues and jakarta EE page referred in answer/solutions. Actually my application don't have maven/graddle and run on binaries.

Please refer to the error message below: 2023-08-04 12:59:40,731 [main] ERROR org.apache.shiro.web.env.EnvironmentLoader [] - Shiro environment initialization failed java.lang.NoClassDefFoundError: javax/servlet/Filter at java.lang.ClassLoader.defineClass1(Native Method) ~[?:?] at java.lang.ClassLoader.defineClass(ClassLoader.java:1012) ~[?:?] at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150) ~[?:?] at org.apache.catalina.loader.WebappClassLoaderBase.findClassInternal(WebappClassLoaderBase.java:2487) ~[catalina.jar:10.1.11] at org.apache.catalina.loader.WebappClassLoaderBase.findClass(WebappClassLoaderBase.java:865) ~[catalina.jar:10.1.11] at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1401) ~[catalina.jar:10.1.11] at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1245) ~[catalina.jar:10.1.11] at java.lang.Class.forName0(Native Method) ~[?:?] at java.lang.Class.forName(Class.java:467) ~[?:?] at org.apache.shiro.lang.util.ClassUtils$ExceptionIgnoringAccessor.loadClass(ClassUtils.java:281) ~[shiro-lang-2.0.0-alpha-3.jar:2.0.0-alpha-3] at org.apache.shiro.lang.util.ClassUtils.forName(ClassUtils.java:151) ~[shiro-lang-2.0.0-alpha-3.jar:2.0.0-alpha-3] at org.apache.shiro.lang.util.ClassUtils.newInstance(ClassUtils.java:193) ~[shiro-lang-2.0.0-alpha-3.jar:2.0.0-alpha-3] at org.apache.shiro.config.ogdl.ReflectionBuilder.createNewInstance(ReflectionBuilder.java:351) ~[shiro-config-ogdl-2.0.0-alpha-3.jar:2.0.0-alpha-3] at org.apache.shiro.config.ogdl.ReflectionBuilder$InstantiationStatement.doExecute(ReflectionBuilder.java:995) ~[shiro-config-ogdl-2.0.0-alpha-3.jar:2.0.0-alpha-3] at org.apache.shiro.config.ogdl.ReflectionBuilder$Statement.execute(ReflectionBuilder.java:955) ~[shiro-config-ogdl-2.0.0-alpha-3.jar:2.0.0-alpha-3] at org.apache.shiro.config.ogdl.ReflectionBuilder$BeanConfigurationProcessor.execute(ReflectionBuilder.java:833) ~[shiro-config-ogdl-2.0.0-alpha-3.jar:2.0.0-alpha-3] at org.apache.shiro.config.ogdl.ReflectionBuilder.buildObjects(ReflectionBuilder.java:304) ~[shiro-config-ogdl-2.0.0-alpha-3.jar:2.0.0-alpha-3] at org.apache.shiro.ini.IniSecurityManagerFactory.buildInstances(IniSecurityManagerFactory.java:184) ~[shiro-core-2.0.0-alpha-3-jakarta.jar:2.0.0-alpha-3] at org.apache.shiro.ini.IniSecurityManagerFactory.createSecurityManager(IniSecurityManagerFactory.java:142) ~[shiro-core-2.0.0-alpha-3-jakarta.jar:2.0.0-alpha-3] at org.apache.shiro.ini.IniSecurityManagerFactory.createSecurityManager(IniSecurityManagerFactory.java:110) ~[shiro-core-2.0.0-alpha-3-jakarta.jar:2.0.0-alpha-3] at org.apache.shiro.ini.IniSecurityManagerFactory.createInstance(IniSecurityManagerFactory.java:101) ~[shiro-core-2.0.0-alpha-3-jakarta.jar:2.0.0-alpha-3] at org.apache.shiro.ini.IniSecurityManagerFactory.createInstance(IniSecurityManagerFactory.java:50) ~[shiro-core-2.0.0-alpha-3-jakarta.jar:2.0.0-alpha-3] at org.apache.shiro.ini.IniFactorySupport.createInstance(IniFactorySupport.java:150) ~[shiro-core-2.0.0-alpha-3-jakarta.jar:2.0.0-alpha-3] at org.apache.shiro.util.AbstractFactory.getInstance(AbstractFactory.java:49) ~[shiro-core-2.0.0-alpha-3-jakarta.jar:2.0.0-alpha-3] at org.apache.shiro.web.env.IniWebEnvironment.createWebSecurityManager(IniWebEnvironment.java:300) ~[shiro-web-2.0.0-alpha-3-jakarta.jar:2.0.0-alpha-3] at org.apache.shiro.web.env.IniWebEnvironment.configure(IniWebEnvironment.java:125) ~[shiro-web-2.0.0-alpha-3-jakarta.jar:2.0.0-alpha-3] at org.apache.shiro.web.env.IniWebEnvironment.init(IniWebEnvironment.java:77) ~[shiro-web-2.0.0-alpha-3-jakarta.jar:2.0.0-alpha-3] at org.apache.shiro.lang.util.LifecycleUtils.init(LifecycleUtils.java:45) ~[shiro-lang-2.0.0-alpha-3.jar:2.0.0-alpha-3] at org.apache.shiro.lang.util.LifecycleUtils.init(LifecycleUtils.java:40) ~[shiro-lang-2.0.0-alpha-3.jar:2.0.0-alpha-3] at org.apache.shiro.web.env.EnvironmentLoader.createEnvironment(EnvironmentLoader.java:319) ~[shiro-web-2.0.0-alpha-3-jakarta.jar:2.0.0-alpha-3] at org.apache.shiro.web.env.EnvironmentLoader.initEnvironment(EnvironmentLoader.java:139) [shiro-web-2.0.0-alpha-3-jakarta.jar:2.0.0-alpha-3] at org.apache.shiro.web.env.EnvironmentLoaderListener.contextInitialized(EnvironmentLoaderListener.java:58) [shiro-web-2.0.0-alpha-3-jakarta.jar:2.0.0-alpha-3] at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4458) [catalina.jar:10.1.11] at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:4896) [catalina.jar:10.1.11] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [catalina.jar:10.1.11] at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:683) [catalina.jar:10.1.11] at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:658) [catalina.jar:10.1.11] at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:713) [catalina.jar:10.1.11] at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1136) [catalina.jar:10.1.11] at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1971) [catalina.jar:10.1.11] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) [?:?] at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?] at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) [tomcat-util.jar:10.1.11] at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:123) [?:?] at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:1046) [catalina.jar:10.1.11] at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:428) [catalina.jar:10.1.11] at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1656) [catalina.jar:10.1.11] at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:309) [catalina.jar:10.1.11] at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123) [catalina.jar:10.1.11] at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:423) [catalina.jar:10.1.11] at org.apache.catalina.util.LifecycleBase.setState(LifecycleBase.java:366) [catalina.jar:10.1.11] at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:893) [catalina.jar:10.1.11] at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:846) [catalina.jar:10.1.11] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [catalina.jar:10.1.11] at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1328) [catalina.jar:10.1.11] at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1318) [catalina.jar:10.1.11] at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?] at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) [tomcat-util.jar:10.1.11] at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:145) [?:?] at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:866) [catalina.jar:10.1.11] at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:241) [catalina.jar:10.1.11] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [catalina.jar:10.1.11] at org.apache.catalina.core.StandardService.startInternal(StandardService.java:428) [catalina.jar:10.1.11] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [catalina.jar:10.1.11] at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:918) [catalina.jar:10.1.11] at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) [catalina.jar:10.1.11] at org.apache.catalina.startup.Catalina.start(Catalina.java:795) [catalina.jar:10.1.11] at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?] at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?] at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?] at java.lang.reflect.Method.invoke(Method.java:568) ~[?:?] at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:347) [bootstrap.jar:10.1.11] at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:478) [bootstrap.jar:10.1.11] Caused by: java.lang.ClassNotFoundException: javax.servlet.Filter at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1437) ~[catalina.jar:10.1.11] at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1245) ~[catalina.jar:10.1.11] ... 73 more

Jars I have added are: image

I have seen the class file of shiro-web jakarta jar and inside I can see we are using jakarta.servlet.Filter. Not sure what I am missing here. Let me know if any other details is needed. In my code base I don't have any javax dependency and java services are running fine on the same code base.

Can anyone help with this. Apologies if it a silly query.

Thanks

lprimak commented 1 year ago

Hi,

unfortunately these types of issues are not possible to diagnose without some kind of a reproducer.

I would suggest going through all contents of your app and see where the javax package is referenced

lprimak commented 1 year ago

Maybe Jarviz tool can be helpful here

lprimak commented 1 year ago

Can you post your shiro.ini also? It looks like something referenced from there is causing the issue

Divyanshgarg commented 1 year ago

post your shiro.ini also? It looks like somet

Thanks for responding. Please refer to below shiro.ini. I will try Jarviz tool and share my findings here.

`[main]

fmconvergeRealm=com.finmechanics.fmconverge.security.ShiroEntityAwareRealm fmAjaxFilter=com.finmechanics.fmcom.crypto.ShiroAjaxAuthenticator fmAuthListener=com.finmechanics.fmconverge.security.FmShiroAuthListener

sha256Matcher = org.apache.shiro.authc.credential.SimpleCredentialsMatcher fmconvergeRealm.credentialsMatcher = $sha256Matcher

securityManager.realms = $fmconvergeRealm

sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager

securityManager.sessionManager = $sessionManager sessionManager.globalSessionTimeout = 18000000

securityManager.authenticator.authenticationListeners=$fmAuthListener

shiro.loginUrl = /login.jsp authc.successUrl = /index.jsp logout.redirectUrl = /logout.jsp

sessionIdGenerator=com.finmechanics.fmcom.crypto.JavaUuidAndJvmRouteSessionIdGenerator cookie = org.apache.shiro.web.servlet.SimpleCookie cookie.name = FMCONVERGE cookie.path = /fmconverge securityManager.sessionManager.sessionIdCookie = $cookie securityManager.sessionManager.sessionIdCookie.secure = false securityManager.sessionManager.sessionDAO.sessionIdGenerator = $sessionIdGenerator sessionManager.sessionIdUrlRewritingEnabled=false

[urls] /login.jsp = authc /logout = logout /logout.jsp = anon /css/ = anon /js/ = anon /extjs/ = anon /dealmakerjs/ = anon /javascripts/ = anon /fonts/ = anon /favicon.ico = anon /error.jsp = anon /images/ = anon /services/ = anon /dwr/call/ = fmAjaxFilter /atmospherePushServlet/ = fmAjaxFilter /** = authc `

fpapon commented 1 year ago

According to the stack trace, it seems to be one of the bean creation define in the ini file that depends on javax.servlet.Filter.

This filter seems to be home made:

fmAjaxFilter=com.finmechanics.fmcom.crypto.ShiroAjaxAuthenticator

@Divyanshgarg: I would suggest to check this classe.

rakeshk15 commented 1 year ago

@Divyanshgarg problem here is that shiro-web artifact is still using javax namespace while Tomcat 10.1.x already on jakarta namespace.

That's why there is no javax.servlet.Filter class at runtime.

Tomcat v9.x support Servlet 4 with javax namespace, may be you can try with that.

Follow this page for using the correct Tomcat version for your use case - https://tomcat.apache.org/whichversion.html

lprimak commented 1 year ago

problem here is that shiro-web artifact is still using javax

Sorry, that is incorrect. He wants to use jakarta namespace, and he is using Shiro -jakarta artifacts. Those are shaded to use jakarta namespace.

rakeshk15 commented 1 year ago

@lprimak i was not aware of shading, I was looking at the dependencies information here - https://mvnrepository.com/artifact/org.apache.shiro/shiro-web/2.0.0-alpha-3 but could not find it using jakarta namespace

image

Also, the binaries from maven (shiro-jakarta-ee-2.0.0-alpha-3.jar and shiro-web-2.0.0-alpha-3.jar) is still using javax namespace.

image image

Can you please point to me which are the correct artifacts to be used for jakarta namespace?

lprimak commented 1 year ago

Please see How to use Jakarta 9+ (jakarta.* namespace) section in the docs: https://shiro.apache.org/jakarta-ee.html

rakeshk15 commented 1 year ago

I see the usage of maven classifier, thanks for pointing it out.

Divyanshgarg commented 1 year ago

@Divyanshgarg: I would suggest to check this classe.

Please refer to the below filter class getting used in my codebase. And FormAuthenticationFilter is also using internally jakarta.servlet.* as I am using jakarta artifact. Let me know what else I can try.

package com.finmechanics.fmcom.crypto;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.apache.shiro.web.servlet.ShiroHttpServletResponse;
import com.finmechanics.logging.FmLogger;
import com.finmechanics.logging.FmLoggerFactory;

import java.io.IOException;

public class ShiroAjaxAuthenticator extends FormAuthenticationFilter {

    protected static final FmLogger logger = FmLoggerFactory.getLogger(ShiroAjaxAuthenticator.class);

    protected boolean isAccessAllowed(ServletRequest request, ServletResponse
            response, Object mappedValue) {
        return super.isAccessAllowed(request,response,mappedValue);
    }

    @Override
    public void doFilterInternal(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws ServletException, IOException {
        super.doFilterInternal(servletRequest,servletResponse,filterChain);
        Subject subject=SecurityUtils.getSubject();
        Session session=subject.getSession(false);
        if(session!=null) {
            session.touch();
        }
    }

    @Override
    protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
        ShiroHttpServletRequest httpServletRequest = (ShiroHttpServletRequest) servletRequest;
        ShiroHttpServletResponse httpServletResponse = (ShiroHttpServletResponse) servletResponse;
        if (isLoginRequest(servletRequest, servletResponse)) {
            return true;
        } else {
            logger.debug("AUTH Unauthenticated dwr request " + httpServletRequest.getRequestURI());
            httpServletResponse.sendError (HttpServletResponse.SC_FORBIDDEN,
                    "Invalid login or else Server is way too busy at this time");
            return false;
        }
    }
}
lprimak commented 1 year ago

I would use jarviz tool to check all of your .class / .jar files for javax usages.

lprimak commented 1 year ago

I am assuming this question was answered. Feel free to reopen it if not.

Divyanshgarg commented 1 year ago

Yes it worked, seems it was pac4j jar which was causing issue. Thanks for the help. Apologies for the late reply.