From: Schelle, D. <Dom...@ip...> - 2015-09-07 08:18:49
|
Hi and thank you for accepting me in this mailing list. I have a problem with spring security and can't quite figure out what the problem is (even though I get an exception that tellls me the problem, I just can't figure out why it occures in that particular section and how to avoid it). In Details: i'm currently trying to implement a Spring Boot webservice with mutual authentication that expects a user certifiace and authenticates and authorizes a user with the details it contains against a ldap server. The mutual authentication works so far, that the server identifies himself to the user and asks for an user certificate. With an example in-memory user the whole authentication and authorization process works fine. However as soon as I implement the LDAP connection I get an "java.lang.IllegalStateException: UserDetailsService is required." exception. Interesting though is that the LDAP configuration itself is working fine when I use an login page where a user is has to prompt his credetnials manualy. So in Short: Login Page + LDAP works, CERT + in-memory User works, CERT + LDAP does not work. here is my Code so far: web/config/Application.java @SpringBootApplication @ComponentScan({ "web.*" }) public class Application extends SpringBootServletInitializer { @Bean public InternalResourceViewResolver viewResolver() { InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); viewResolver.setViewClass(JstlView.class); viewResolver.setPrefix("/WEB-INF/jsp/"); viewResolver.setSuffix(".jsp"); return viewResolver; } public static void main(String[] args) throws Exception { SpringApplication.run(Application.class, args); } @Bean public EmbeddedServletContainerFactory servletContainer() { TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory(); tomcat.addAdditionalTomcatConnectors(createSslConnector()); return tomcat; } // ************************************************************************************************* // Mutual Cert Authentication // ************************************************************************************************* private Connector createSslConnector() { Connector connector = new Connector( "org.apache.coyote.http11.Http11NioProtocol"); Http11NioProtocol protocol = (Http11NioProtocol) connector .getProtocolHandler(); try { File keystore = new ClassPathResource("server.jks").getFile(); File truststore = new ClassPathResource("cacerts.jks").getFile(); connector.setScheme("https"); connector.setSecure(true); connector.setPort(8443); protocol.setSSLEnabled(true); protocol.setKeystoreFile(keystore.getAbsolutePath()); protocol.setKeystorePass("toor"); //example password protocol.setTruststoreFile(truststore.getAbsolutePath()); protocol.setTruststorePass("toor"); //example passsword protocol.setKeyAlias("server"); protocol.setClientAuth("want"); protocol.setSslProtocol("TLS"); return connector; } catch (IOException ex) { throw new IllegalStateException("can't access keystore: [" + "keystore" + "] or truststore: [" + "keystore" + "]", ex); } } // ************************************************************************************************* // The Authentication Manager Bean provides the source that userdata gets // authenticated against. In this Scenario a ldap server is used. // ************************************************************************************************* @Bean public DefaultSpringSecurityContextSource getSource() throws Exception { String address = "ldap://lokalhost:389/dc=ldap"; //example url String ldapUser = "cn=admin,dc=ldap"; //example login String ldapPassword = "toor"; //example password DefaultSpringSecurityContextSource source = new DefaultSpringSecurityContextSource( address); source.setUserDn(ldapUser); source.setPassword(ldapPassword); source.afterPropertiesSet(); return source; } } web/config/WebSecurity.java @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private DefaultSpringSecurityContextSource source; @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.ldapAuthentication().contextSource(source) .userSearchBase("dc=users,dc=ldap") .userDnPatterns("cn={0},dc=users") .groupSearchBase("ou=groups") ; } @Override protected void configure(HttpSecurity http) throws Exception { // ************************************************************************************************* // Insert pages that need propper authentication/authorization here // ************************************************************************************************* http .x509().subjectPrincipalRegex("CN=(.*?),").and() .authorizeRequests() .antMatchers("/**") .access("hasRole('ROLE_USER')") .and() .csrf().disable(); } } The pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>SpringCertAuth</groupId> <artifactId>spring-cert-authentication</artifactId> <version>0.1.0</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.2.5.RELEASE</version> </parent> <dependencies> <!-- ldap --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-ldap</artifactId> </dependency> <dependency> <groupId>org.apache.directory.server</groupId> <artifactId>apacheds-server-jndi</artifactId> <version>1.5.5</version> </dependency> <!-- end ldap --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <properties> <main.basedir>${basedir}/../..</main.basedir> <java.version>1.8</java.version> </properties> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> The web/controller/HomeController.java @Controller public class HomeController { @RequestMapping("/welcome") public ModelAndView index() { ModelAndView model = new ModelAndView(); model.addObject("title","Secure Web Application"); model.addObject("message", "this is the welcome page"); model.setViewName("welcome"); return model; } } And the webapp/WEB-INF/jsp/welcome.jsp <%@page session="false"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <html> <body> <h1>Title : ${title}</h1> <h1>Message : ${message}</h1> </body> </html> PS: The certificates I am using are self signed and lie in the src/main/resources folder. I hope someone can help me. Best regards Dominik |