Java Spring MVC + Security Hello World -> Could not autowire ...

Timmey92

Commodore
Registriert
Okt. 2008
Beiträge
4.568
Moin,

ich baue gerade zum Weiterbilden an einem Webprojekt, auf Basis von Spring MVC + Apache Tiles. Das läuft auch soweit alles, Annotation basierte Controller mit Tileviews, supi.
Spring in der Version 4.0.0.Release und Spring Security in 3.2.0.Release
Jetzt will ich eine Loginmaske etc. einbauen, die auf Spring Security aufsetzt.

Dazu habe ich mich an der offiziellen Doku orientiert (http://docs.spring.io/spring-security/site/docs/3.2.x/guides/hellomvc.html#security-config-java) und an diesem Artikel http://spring.io/blog/2013/07/03/spring-security-java-config-preview-web-security/.

Der Fehler tritt in der SecurityConfig.java Datei auf:
auth: Could not autowire. No Beans of AuthenticationManagerBuilder type found.

Code:
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
...
}

Class: SecurityWebApplicationInitializer
Code:
import org.springframework.security.web.context.*;

public class SecurityWebApplicationInitializer
        extends AbstractSecurityWebApplicationInitializer {
}

Beim make spuckt der compiler noch zusätzlich folgende Fehler aus:

Code:
src\...\config\SecurityWebApplicationInitializer.java
java: cannot access javax.servlet.ServletException
  class file for javax.servlet.ServletException not found
src\...\config\SecurityConfig.java
java: cannot access javax.servlet.Filter
  class file for javax.servlet.Filter not found

Habt ihr da eine Idee? Habe mich eigentlich genau an das Tutorial gehalten, aber irgendwie will es nicht...

Anbei meine pom.xml
Code:
<properties>
    <java.version>1.7</java.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <hibernate.jpa.version>2.0-cr-1</hibernate.jpa.version>
    <spring.version>4.0.0.RELEASE</spring.version>
    <spring.security.version>3.2.0.RELEASE</spring.security.version>
    <apache.tiles.version>3.0.3</apache.tiles.version>
    <org.slf4j.version>1.7.5</org.slf4j.version>
    <log4j.version>1.2.17</log4j.version>
    <jstl.version>1.2</jstl.version>
    <maven.plugins.compiler.version>3.1</maven.plugins.compiler.version>
</properties>

  <dependencies>
 	<dependency>
  		<groupId>junit</groupId>
  		<artifactId>junit</artifactId>
  		<version>4.8.1</version>
  		<type>jar</type>
  		<scope>compile</scope>
  	</dependency>
  	<dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-web</artifactId>
    	<version>${spring.version}</version>
    	<type>jar</type>
    	<scope>compile</scope>
    </dependency>
    <dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-core</artifactId>
    	<version>${spring.version}</version>
    	<type>jar</type>
    	<scope>compile</scope>
    </dependency>
    <dependency>
    	<groupId>log4j</groupId>
    	<artifactId>log4j</artifactId>
    	<version>${log4j.version}</version>
    	<type>jar</type>
    	<scope>compile</scope>
    </dependency>
    <dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-tx</artifactId>
    	<version>${spring.version}</version>
    	<type>jar</type>
    	<scope>compile</scope>
    </dependency>
    <dependency>
    	<groupId>jstl</groupId>
    	<artifactId>jstl</artifactId>
    	<version>${jstl.version}</version>
    	<type>jar</type>
    	<scope>compile</scope>
    </dependency>
    <dependency>
    	<groupId>taglibs</groupId>
    	<artifactId>standard</artifactId>
    	<version>1.1.2</version>
    	<type>jar</type>
    	<scope>compile</scope>
    </dependency>
    <dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-webmvc</artifactId>
    	<version>${spring.version}</version>
    	<type>jar</type>
    	<scope>compile</scope>
    </dependency>
    <dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-aop</artifactId>
    	<version>${spring.version}</version>
    	<type>jar</type>
    	<scope>compile</scope>
    </dependency>
      <dependency>
          <groupId>org.springframework.security</groupId>
          <artifactId>spring-security-web</artifactId>
          <version>${spring.security.version}</version>
      </dependency>
      <dependency>
          <groupId>org.springframework.security</groupId>
          <artifactId>spring-security-config</artifactId>
          <version>${spring.security.version}</version>
      </dependency>
    <dependency>
    	<groupId>org.apache.tiles</groupId>
    	<artifactId>tiles-core</artifactId>
    	<version>${apache.tiles.version}</version>
    	<type>jar</type>
    	<scope>compile</scope>
    </dependency>
    <dependency>
    	<groupId>org.apache.tiles</groupId>
    	<artifactId>tiles-template</artifactId>
    	<version>${apache.tiles.version}</version>
    	<type>jar</type>
    	<scope>compile</scope>
    </dependency>
    <dependency>
    	<groupId>org.apache.tiles</groupId>
    	<artifactId>tiles-jsp</artifactId>
    	<version>${apache.tiles.version}</version>
    	<type>jar</type>
    	<scope>compile</scope>
    </dependency>
    <dependency>
    	<groupId>org.apache.tiles</groupId>
    	<artifactId>tiles-servlet</artifactId>
    	<version>${apache.tiles.version}</version>
    	<type>jar</type>
    	<scope>compile</scope>
    </dependency>
    <dependency>
    	<groupId>org.slf4j</groupId>
    	<artifactId>slf4j-api</artifactId>
    	<version>${org.slf4j.version}</version>
    	<type>jar</type>
    	<scope>compile</scope>
    </dependency>
    <dependency>
    	<groupId>org.slf4j</groupId>
    	<artifactId>slf4j-log4j12</artifactId>
    	<version>${org.slf4j.version}</version>
    	<type>jar</type>
    	<scope>compile</scope>
    </dependency>
      <dependency>
          <groupId>org.slf4j</groupId>
          <artifactId>jcl-over-slf4j</artifactId>
          <version>${org.slf4j.version}</version>
      </dependency>
  </dependencies>
  <build>
    <finalName>spring-tiles</finalName>
    <plugins>
    	<plugin>
    		<groupId>org.apache.maven.plugins</groupId>
    		<artifactId>maven-compiler-plugin</artifactId>
    		<version>${maven.plugins.compiler.version}</version>
    		<configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
            </configuration>
    	</plugin>
    </plugins>
  </build>
 
Zuletzt bearbeitet:
Na, die Fehlermeldung ist doch wohl eindeutig. Es gibt keine @Bean vom Typ "AuthenticationManagerBuilder". ;-)

Ich schau mal eben, wie ich das bei uns im Projekt gelöst habe. Man braucht auf jeden Fall kein @Autowired, sondern überschreibt nur eine Methode. In 2 Minuten gibt's die Antwort.

EDIT:
Code:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	/* ... */

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth
			.userDetailsService(userDetailsService())
			.passwordEncoder(passwordEncoder());
	}

	@Override
	@Bean(name="authenticationManager")
	public AuthenticationManager authenticationManagerBean() throws Exception {
		return super.authenticationManagerBean();
	}
	
	@Bean
	protected UserDetailsService userDetailsService() {
		return new MyCustomUserDetailsServiceImpl();
	}
	
	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}

}
 
Zuletzt bearbeitet:
Danke schon mal :) gibts da noch weitere Config Klassen die man braucht (oder hast du da noch XML Config?), damit es läuft?
 
XML hab ich in unserem Projekt gekillt und das schon vor Monaten :D

Naja, mit dieser SpringSecurity Klasse bekommst du natürlich nur die Security Chain ans laufen. Für Spring MVC brauchst du natürlich noch mehr.

Ich habe vor 2 Monaten mal ein winziges Example Projekt bei Github hochgeladen. Basiert allerdings noch auf BETA Versionen von Spring 4 und SpringSecurity 3.2 und nutzt LDAP zur Authentifizierung und MongoDB als Datenbank.

Für dich interessante Klassen sind hier:
- Spring Config: https://github.com/benneq/spring-ex...webapp/src/main/java/de/benneq/example/webapp
- Security Config: https://github.com/benneq/spring-ex...src/main/java/de/benneq/example/core/security
- Config Property Files: https://github.com/benneq/spring-example-project/tree/master/webapp/src/main/resources

Ist gerade alles ein wenig seltsam geordnet :D Aber es funktioniert (zumindest tat es das vor 2 Monaten noch).



EDIT: Im Grunde läuft es so:

1. Tomcat sucht beim Start nach bestimmten Klassen und "startet" diese. In meinem Projekt sind das: "WebApplicationInitializer" und "SecurityWebApplicationInitializer". Diese Klassen implementieren irgendwo tief drunter ein Interface aus der Servlet API, daher kann Tomcat (und auch alle anderen Programme, die die Servlet API nutzen) diese Klassen finden und starten.
2. Die "@Order" Annotation bestimmt in welcher Reihenfolge die geladen werden (wichtig!!)
3. In "WebApplicationInitializer" stehen dann weitere Klassen die geladen werden in den Methoden "getRootConfigClasses" und "getServletConfigClasses"
4. Dort ist die Klasse "WebConfig" enthalten, welche den üblichen ComponentScan vornimmt und die Controller registriert (via "@ComponentScan") und konfiguriert (Jackson & co).
5. Die "AppConfig" registriert die "@Service" Klassen.
6. Der "SecurityWebApplicationInitializer" sucht (automatisch soweit ich mich erinnere) und findet und initialisiert "SecurityConfig" und "GlobalMethodSecurityConfig"


Ich hoffe, das hilft erstmal ^^


EDIT2:
In meinem Projekt läuft die Authentifizierung mittels eines selbst geschriebenen "@Controller" (die Lösung gefällt mir aber noch nicht so 100%): https://github.com/benneq/spring-ex...mple/core/security/web/SessionController.java

Für dich wäre evtl. eher sowas interessant:
Code:
public class SecurityConfig extends WebSecurityConfigurerAdapter {
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {		
		http
			.formLogin()
				.usernameParameter("username")
				.passwordParameter("password")
				.loginPage("/login/index")
				.failureUrl("/login/index?login_error=true")
				.loginProcessingUrl("/j_spring_security_check")
				.defaultSuccessUrl("/app/initialize")
				.and()
			.logout()
				.logoutUrl("/login/logout")
				.invalidateHttpSession(true)
				.logoutSuccessUrl("/login/index");
	}

	/* ... */

}
 
Zuletzt bearbeitet:
Also irgendwie will er bei mir nicht, wenn ich dein Projekt auschecke, meldet zumindest IDEA keine Fehler, wenn ich den Config Code kopiere, sagt er unter anderem das @Override falsch ist, weil diese Methode keine Methode der Superklasse überschreibt (in deinem Projekt hingegen ist das völlig in Ordnung!?).

Ich fang jetzt noch mal mit dem Stand von gestern an, bevor ich Spring Security implementieren wollte und versuch deinen Code zu integrieren.

Deine Anmerkungen sind auf jeden Fall sehr hilfreich um das ganze auch ein wenig zu durchblicken ... hast du nicht mal eine web.xml!?

Edith sagt: läuft! :D Also immerhin bekomme ich jetzt einen hässlichen Login Screen, das sieht doch gut aus! Da kann ich drauf aufsetzen :cool_alt:
Die Doku ist anscheinend fehlerhaft..

Die normale Spring MVC Config mit Apache Tiles lasse ich mal besser in der XML.

Vielen dank!
 
Zuletzt bearbeitet:
Hast du den Code so ausgecheckt und gestartet? (ich nutze Eclipse 4.3)

Auf jeden Fall hab ich nicht mal 'ne web.xml.

Die Dokus sind teilweise minimal out of date. Scheinbar haben sie die Signatur von 1-2 Klassen zwischen Spring Security 3.2.RC1 und 3.2.RELEASE noch geändert gehabt . . .

Im Prinzip ist es auch egal, ob man nun XML oder JavaConfig nimmt, aber ich komme halt mit dem Java Zeug besser klar und (geht bestimmt auch irgendwie in XML) kann beim Booten der App dynamisch konfigurieren - z.B. anhand der Wetterdaten auf den Philippinen :D

Aber im Großen und Ganzen kannst du deine XML Config problemlos in eine JavaConfig übersetzen, die Namen der XML Elemente sind meist Methoden-Namen in einer der JavaConfig Files und die Klassennamen, die man in der XML Config angibt bleiben natürlich dieselben.
 
Zurück
Oben