LdapCtxFactory because module java.naming does not export com.sun.jndi.ldap to unnamed module
Asked Answered
E

4

5

WebSecurityConfigurerAdapter:

@Component
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
   @Override
   protected void configure(HttpSecurity httpSecurity) throws Exception
   {
      httpSecurity
               .authorizeRequests()
               .antMatchers("/abc/**").permitAll()
               .anyRequest()
               .authenticated()
               .and()
               .csrf()
               .disable()
               .httpBasic();
   }

   @Override
   public void configure(AuthenticationManagerBuilder auth) throws Exception
   {
      auth.ldapAuthentication()
          .userDnPatterns("uid={0},ou=people")
          .userSearchBase("ou=people")
          .userSearchFilter("uid={0}")
          .groupSearchBase("ou=groups")
          .groupSearchFilter("uniqueMember={0}")
          .contextSource()
          .url("ldap://localhost:8389/dc=concretepage,dc=com")
          .and()
          .passwordCompare()
          .passwordEncoder(passwordEncoder())
          .passwordAttribute("userPassword");
   }

   @Bean
   public PasswordEncoder passwordEncoder() {
      BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
      return passwordEncoder;
   }

Spring-Version: SPRING_BOOT_VERSION = "2.6.6"

plugins {
    id 'java-library'
}

dependencies {
    implementation "org.springframework.boot:spring-boot:${SPRING_BOOT_VERSION}"
    implementation "org.springframework.boot:spring-boot-starter-web:${SPRING_BOOT_VERSION}"
    implementation "org.springframework.boot:spring-boot-starter-thymeleaf:${SPRING_BOOT_VERSION}"

    api "javax.servlet:javax.servlet-api:${JAVAX_SERVLET_VERSION}"

    compileOnly 'io.crnk:crnk-gen-java' 
    annotationProcessor 'io.crnk:crnk-gen-java'

    gradle.beforeProject { Project project ->
        project.with {
            apply plugin: 'io.spring.dependency-management'
            dependencyManagement {
                imports {
                    mavenBom "io.crnk:crnk-bom:${CRNK_VERSION}"
                }
            }
        }
    }


    implementation platform("io.crnk:crnk-bom:${CRNK_VERSION}")
    annotationProcessor platform("io.crnk:crnk-bom:${CRNK_VERSION}")

    implementation "io.crnk:crnk-setup-spring-boot2"
    implementation "io.crnk:crnk-home"

    implementation "io.crnk:crnk-security"
    implementation 'org.springframework.boot:spring-boot-starter-security:2.7.2'
    implementation 'org.springframework.ldap:spring-ldap-core'
    implementation 'org.springframework.security:spring-security-ldap:5.4.3'
    implementation 'com.unboundid:unboundid-ldapsdk:4.0.14'

    testImplementation("org.springframework.boot:spring-boot-starter-test:${SPRING_BOOT_VERSION}")
}

gradle.properties:

systemProp.http.ssl.insecure=true
systemProp.http.ssl.allowall=true
systemProp.http.ssl.ignore.validity.dates=true

org.gradle.jvmargs=-Djavax.net.ssl.trustStore="./cacerts" -Djavax.net.ssl.trustStorePassword=changeit \
  --add-exports java.naming/com.sun.jndi.ldap=spring.ldap.core

./gradlew --version

------------------------------------------------------------
Gradle 7.4.2
------------------------------------------------------------

Build time:   2022-03-31 15:25:29 UTC
Revision:     540473b8118064efcc264694cbcaa4b677f61041

Kotlin:       1.5.31
Groovy:       3.0.9
Ant:          Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM:          17.0.2 (Oracle Corporation 17.0.2+8-86)
OS:           Windows 10 10.0 amd64

The error:

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2022.08.02 07:16:32.051 [main] ERROR o.s.boot.SpringApplication:830 - Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is java.lang.IllegalAccessError: class org.springframework.ldap.core.support.AbstractContextSource (in unnamed module @0x1d296da) cannot access class com.sun.jndi.ldap.LdapCtxFactory (in module java.naming) because module java.naming does not export com.sun.jndi.ldap to unnamed module @0x1d296da
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:486)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:953)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301)
Elspeth answered 2/8, 2022 at 5:29 Comment(0)
S
8

Try adding --add-exports java.naming/com.sun.jndi.ldap=ALL-UNNAMED instead of --add-exports java.naming/com.sun.jndi.ldap=spring.ldap.core to your JVM arguments.

But a better solution would be to align all the dependency versions with the Spring Boot version you use (2.6.6):

  • for org.springframework.boot:spring-boot-starter-security either remove the version or set 2.6.6
  • org.springframework.security:spring-security-ldap:5.4.3 is too old, should be at least version 5.6.2. With this one chances are you won't need any explicit --add-exports at all.
  • remove org.springframework.ldap:spring-ldap-core - org.springframework.security:spring-security-ldap brings it in automatically.
Snowfall answered 2/8, 2022 at 6:49 Comment(3)
changed but same error ;-(Elspeth
Worked in my case. Thanks a lot @dekkard. --add-exports java.naming/com.sun.jndi.ldap=ALL-UNNAMEDClash
This is a bad solution. See https://mcmap.net/q/1905648/-ldapctxfactory-because-module-java-naming-does-not-export-com-sun-jndi-ldap-to-unnamed-module for thew correct solution.Vendue
T
3

For me it worked to add:

--add-opens=java.naming/com.sun.jndi.ldap=ALL-UNNAMED

instead of --add-exports

Tincture answered 21/9, 2022 at 15:16 Comment(0)
I
1

This solution may be applicable to those who don't want to use --add-exports explicitly.
In my case, the issue was resolved after upgrading and using correct ldap core jar. Previously it was using 2.2.0.RELEASE version.

<dependency>
    <groupId>org.springframework.ldap</groupId>
    <artifactId>spring-ldap-core</artifactId>
    <!-- version>2.2.0.RELEASE</version -->
    <version>3.0.2</version>
</dependency>
Indiscrete answered 10/5, 2023 at 10:18 Comment(2)
Yup. For Java 17 you need SpringBoot 3.x. Earlier versions of Spring do naughty things that involve accessing JDK internals. Java 17 says to Spring "No dude ... don't do that".Vendue
Sometimes you can use Java 17 but not Spring 3, e.g. webapp on JBoss EAP 7.Lundin
P
0

In my case, I was using the class com.sun.jndi.ldap.LdapCtxFactory at compile time and hence adding --add-exports=java.naming/com.sun.jndi.ldap=ALL-UNNAMED to org.gradle.jvmargs didn't help. I needed to pass it as a compiler arg. Something like the below:

compileJava {
    options.compilerArgs += [
        '--add-exports=java.naming/com.sun.jndi.ldap=ALL-UNNAMED'
    ]
}
Pleadings answered 27/9 at 0:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.