Spring Security und GAE/J

Da die normale Spring-Security.jar nur semi-compatible ist, laden wir uns eine modifizierte Version hier herunter:Download

Diese kommt dann statt der spring-security.jar in unseren Classpath.

Danach wird die “Filterkette” von Spring in der web.xml konfiguriert und die application-security-context.xml eingebunden:

	
contextConfigLocation

			WEB-INF/application-context.xml
			WEB-INF/application-security-context.xml
			
	
	
  		springSecurityFilterChain
  		org.springframework.web.filter.DelegatingFilterProxy
	

	
  		springSecurityFilterChain
  		/*
	

Da wir unseren UserDetailsService, sowie unsere UserDetails und GrantedAuthority selber schreiben müssen, mußte ich ein etwas größeres Refactoring machen. Ich werde aber, wenn alles fertig ist, die App im SVN öffentlich machen, so das sich jeder die Sourcen downloaden kann.

Als nächstes wird die application-security-context.xml konfiguriert:
(Diese ist schon für später etwas umfangreicher geworden, aber ich denke, man findet sich trotzdem noch gut zurecht)

 

 	
 		
 		
 		

 	

 	
		
			
		
	

	

 	

 	

 	 


	 

 	

  	


  		

 	


Als nächstes schreiben wir uns unseren UserDetailsService und unsere GrantedAuthority:

public class GAEGrantedAuthority implements GrantedAuthority
{

	public static final String ROLE_USER 	= "ROLE_USER";
	public static final String ROLE_ADMIN 	= "ROLE_ADMIN";

	@PrimaryKey
	@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
	private Key key;

	@Persistent
	private String role;

	@Override
	public String getAuthority()
	{
		return role;
	}

	@Override
	public int compareTo(Object o)
	{
		if (o != null && o instanceof GrantedAuthority)
		{
			GrantedAuthority rhs = (GrantedAuthority) o;
			return this.role.compareTo(rhs.getAuthority());
		}
		return -1;
	}
//getter/setter
}
public class GAEUserdetailsService implements UserDetailsService
{
	private UserDAO userDAO;

	@Override
	public UserDetails loadUserByUsername(String arg0)
			throws UsernameNotFoundException, DataAccessException
	{
		UserDetails userDetails = userDAO.findUserByUsername(arg0);
		if(null == userDetails)
			throw new UsernameNotFoundException("Invalid User Credentials");

		return userDetails;
	}

	public void setUserDAO(UserDAO userDAO)
	{
		this.userDAO = userDAO;
	}

}

Anschließend implementiert der User noch die UserDetails:

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class User implements UserDetails
{
	@PrimaryKey
	@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
	private Key key;

	@Persistent
	private String password;

	@Persistent
	private String username;

	@Persistent
	private boolean enabled;

	@Persistent
	private boolean accountNonLocked;

	@Persistent
	private boolean credentialsNonExpired;

	@Persistent
	private boolean accountNonExpired;

	@Persistent(defaultFetchGroup = "true")
	private List grantedAuthorities = Lists.newArrayList();

	@Persistent
	private String email;

	@Persistent
	private BigDecimal weight;

	@Persistent
	private BigDecimal desiredWeight;

	@Persistent(mappedBy = "user",defaultFetchGroup = "true")
	private List weightUnits  = Lists.newArrayList();

	@Override
	public GrantedAuthority[] getAuthorities()
	{
		return (GrantedAuthority[]) grantedAuthorities.toArray(new GrantedAuthority[]{});
	}
//getter,setter...
}

Die in der application-security.xml eingetragenen MyAuthenticationProcessingFilter und MyAuthenticationEntryPoint kann man vorerst leer implementieren und verdrahten …

Natürlich müssen jetzt noch Controller und JSPs für den “sicheren Bereich” angelegt werden, aber das sollte ja kein Problem sein.

Interessanterweise funktioniert alles, wenn ich die App auf meinem Rechner deploye, jedoch fliegen in der Cloud noch Exceptions!
Dies liegt daran, das Strings einen StringTrimmerEditor benötigen! Entweder registriert jeder Controller seinen eigenen CustomEditor oder man registriert global einen Editor für alle Strings. Ich habe gelesen, das man besser auch sämtliche Variablen, die das BackingObject im View benutzt, lieber nicht als primitive Datentypen anlegt!

Inzwischen läuft alles schon testmäßig in der Cloud unter Link

Falls einer Lust & Zeit hat, Oberflächen zu designen, kann er sich ja mal melden!

Als nächstes werde ich die Eingabeoberflächen programmieren (darauf gehe ich aber nicht ein) und ich werde versuchen, irgendewas ähnlich JFreeChart oder so einzubinden, damit ich Verlaufsgrafiken darstellen kann. Außerdem versuche ich, Springs MailSender einzubinden…