Add LDAP support.

This commit is contained in:
Paulo Gustavo Veiga 2013-02-17 21:00:08 -03:00
parent 51f531f6b4
commit 3ff67910c9
13 changed files with 203 additions and 21 deletions

View File

@ -77,6 +77,12 @@
<version>${org.springframework.version}</version> <version>${org.springframework.version}</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-ldap</artifactId>
<version>${org.springframework.version}</version>
<scope>compile</scope>
</dependency>
<dependency> <dependency>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId> <artifactId>spring-beans</artifactId>

View File

@ -85,7 +85,7 @@ public class AdminController extends BaseController {
} }
// Finally create the user ... // Finally create the user ...
userService.createUser(delegated, false); userService.createUser(delegated, false,true);
response.setHeader("Location", "/service/admin/users/" + user.getId()); response.setHeader("Location", "/service/admin/users/" + user.getId());
} }

View File

@ -27,10 +27,10 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
public class UserDetails implements org.springframework.security.core.userdetails.UserDetails { public class UserDetails implements org.springframework.security.core.userdetails.UserDetails {
private com.wisemapping.model.User user; private com.wisemapping.model.User user;
private boolean isAdmin; private boolean isAdmin;
public UserDetails(@NotNull final com.wisemapping.model.User user, boolean isAdmin) { public UserDetails(@NotNull final com.wisemapping.model.User user, boolean isAdmin) {
this.user = user; this.user = user;
this.isAdmin = isAdmin; this.isAdmin = isAdmin;
} }

View File

@ -18,13 +18,12 @@
package com.wisemapping.security; package com.wisemapping.security;
import com.wisemapping.dao.UserManager;
import com.wisemapping.model.User; import com.wisemapping.model.User;
import com.wisemapping.service.UserService; import com.wisemapping.service.UserService;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessException;
import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.core.userdetails.UsernameNotFoundException;
@ -37,7 +36,7 @@ public class UserDetailsService
@Override @Override
public UserDetails loadUserByUsername(@NotNull String email) throws UsernameNotFoundException, DataAccessException { public UserDetails loadUserByUsername(@NotNull String email) throws UsernameNotFoundException, DataAccessException {
final User user = userService.getUserBy(email); final User user = userService.getUserBy(email);
if (user != null) { if (user != null) {
return new UserDetails(user, isAdmin(email)); return new UserDetails(user, isAdmin(email));
} else { } else {

View File

@ -0,0 +1,79 @@
package com.wisemapping.security.ldap;
import com.wisemapping.exceptions.WiseMappingException;
import com.wisemapping.model.User;
import com.wisemapping.security.UserDetails;
import com.wisemapping.service.UserService;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.ldap.userdetails.UserDetailsContextMapper;
import java.util.Calendar;
import java.util.Collection;
public class LdapUserDetailsContextMapper implements UserDetailsContextMapper {
private UserService userService;
private String adminUser;
public UserService getUserService() {
return userService;
}
public void setUserService(UserService userService) {
this.userService = userService;
}
private boolean isAdmin(@Nullable String email) {
return email != null && adminUser != null && email.trim().endsWith(adminUser);
}
public String getAdminUser() {
return adminUser;
}
public void setAdminUser(String adminUser) {
this.adminUser = adminUser;
}
@Override
public UserDetails mapUserFromContext(@NotNull DirContextOperations userData,
String email, Collection<? extends GrantedAuthority> arg2) {
User user = userService.getUserBy(email);
if (user == null) {
// If the user was not found in the database, create a new one ...
user = new User();
user.setEmail(email);
final String firstName = userData.getStringAttribute("givenName");
user.setFirstname(firstName);
final String lastName = userData.getStringAttribute("sn");
user.setLastname(lastName);
user.setPassword(email);
final Calendar now = Calendar.getInstance();
user.setActivationDate(now);
try {
userService.createUser(user, false,false);
} catch (WiseMappingException e) {
throw new IllegalStateException(e);
}
}
return new UserDetails(user, isAdmin(email));
}
@Override
public void mapUserToContext(org.springframework.security.core.userdetails.UserDetails userDetails, DirContextAdapter dirContextAdapter) {
// To be implemented ...
}
}

View File

@ -26,7 +26,7 @@ public interface UserService {
public void activateAccount(long code) throws InvalidActivationCodeException; public void activateAccount(long code) throws InvalidActivationCodeException;
public User createUser(@NotNull User user, boolean emailConfirmEnabled) throws WiseMappingException; public User createUser(@NotNull User user, boolean emailConfirmEnabled,boolean welcomeEmail) throws WiseMappingException;
public void changePassword(@NotNull User user); public void changePassword(@NotNull User user);
@ -41,4 +41,6 @@ public interface UserService {
public void deleteUser(@NotNull User user); public void deleteUser(@NotNull User user);
public void auditLogin(@NotNull User user); public void auditLogin(@NotNull User user);
public User getCasUserBy(String uid);
} }

View File

@ -107,7 +107,7 @@ public class UserServiceImpl
userManager.auditLogin(accessAuditory); userManager.auditLogin(accessAuditory);
} }
public User createUser(@NotNull User user, boolean emailConfirmEnabled) throws WiseMappingException { public User createUser(@NotNull User user, boolean emailConfirmEnabled, boolean welcomeEmail) throws WiseMappingException {
final UUID uuid = UUID.randomUUID(); final UUID uuid = UUID.randomUUID();
user.setCreationDate(Calendar.getInstance()); user.setCreationDate(Calendar.getInstance());
user.setActivationCode(uuid.getLeastSignificantBits()); user.setActivationCode(uuid.getLeastSignificantBits());
@ -120,6 +120,7 @@ public class UserServiceImpl
} }
Collaborator col = userManager.getCollaboratorBy(user.getEmail()); Collaborator col = userManager.getCollaboratorBy(user.getEmail());
if (col != null) { if (col != null) {
userManager.createUser(user, col); userManager.createUser(user, col);
} else { } else {
@ -134,7 +135,7 @@ public class UserServiceImpl
// Send registration email. // Send registration email.
if (emailConfirmEnabled) { if (emailConfirmEnabled) {
notificationService.sendRegistrationEmail(user); notificationService.sendRegistrationEmail(user);
} else { } else if (welcomeEmail) {
// Send a welcome email .. // Send a welcome email ..
notificationService.newAccountCreated(user); notificationService.newAccountCreated(user);
} }
@ -205,4 +206,10 @@ public class UserServiceImpl
public void setVelocityEngine(VelocityEngine velocityEngine) { public void setVelocityEngine(VelocityEngine velocityEngine) {
this.velocityEngine = velocityEngine; this.velocityEngine = velocityEngine;
} }
@Override
public User getCasUserBy(String uid) {
// TODO Auto-generated method stub
return null;
}
} }

View File

@ -110,7 +110,7 @@ public class UsersController {
user.setPassword(userBean.getPassword()); user.setPassword(userBean.getPassword());
boolean confirmRegistrationByEmail = false; boolean confirmRegistrationByEmail = false;
userService.createUser(user, confirmRegistrationByEmail); userService.createUser(user, confirmRegistrationByEmail,true);
// Forward to the success view ... // Forward to the success view ...
result = new ModelAndView("userRegistrationSuccess"); result = new ModelAndView("userRegistrationSuccess");

View File

@ -98,3 +98,25 @@ google.analytics.account=UA-XXXX
# Google Ads enable # Google Ads enable
################################################################################## ##################################################################################
google.ads.enabled=false google.ads.enabled=false
#######################################################################################
LDAP Configuration Section
#######################################################################################
security.ldap.enabled=false
security.ldap.server=ldap://localhost:389
security.ldap.server.user=cn=pveiga,dc=wisemapping,dc=com
security.ldap.server.password=password
security.ldap.basedn=dc=wisemapping,dc=com
security.ldap.subDn=people
security.ldap.auth.attribute=mail
#######################################################################################

View File

@ -28,6 +28,7 @@
- The application context is then available via - The application context is then available via
- WebApplicationContextUtils.getWebApplicationContext(servletContext). - WebApplicationContextUtils.getWebApplicationContext(servletContext).
--> -->
<listener> <listener>
<listener-class>com.wisemapping.service.HibernateAppListener</listener-class> <listener-class>com.wisemapping.service.HibernateAppListener</listener-class>
</listener> </listener>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider ref="dbAuthenticationProvider"/>
<sec:authentication-provider user-service-ref="userDetailsService"/>
</sec:authentication-manager>
<bean id="dbAuthenticationProvider" class="com.wisemapping.security.AuthenticationProvider">
<property name="userDetailsService" ref="userDetailsService"/>
<property name="encoder" ref="encoder"/>
</bean>
</beans>

View File

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<sec:authentication-manager>
<sec:authentication-provider ref="ldapAuthProvider"/>
</sec:authentication-manager>
<!-- ================================================== -->
<!-- LDAP Connection settings -->
<!-- ================================================== -->
<bean id="contextSource" class="org.springframework.ldap.core.support.LdapContextSource">
<property name="url" value="${security.ldap.server}"/>
<property name="userDn" value="${security.ldap.server.user}"/>
<property name="password" value="${security.ldap.server.password}"/>
<property name="base" value="${security.ldap.basedn}"/>
</bean>
<!-- ================================================== -->
<!-- Authentication and Authorization Handlers -->
<!-- ================================================== -->
<bean id="ldapAuthProvider"
class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
<constructor-arg>
<bean class="org.springframework.security.ldap.authentication.BindAuthenticator">
<constructor-arg ref="contextSource"/>
<property name="userSearch" ref="ldapUserSearch"/>
</bean>
</constructor-arg>
<property name="userDetailsContextMapper" ref="userDetailsContextMapper"/>
</bean>
<bean id="userDetailsContextMapper" class="com.wisemapping.security.ldap.LdapUserDetailsContextMapper">
<property name="userService" ref="userService"/>
</bean>
<bean id="ldapUserSearch"
class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<constructor-arg index="0" value="ou=${security.ldap.subDn}"/>
<constructor-arg index="1" value="(${security.ldap.auth.attribute}={0})"/>
<constructor-arg index="2" ref="contextSource"/>
<property name="searchSubtree" value="true"/>
</bean>
</beans>

View File

@ -56,18 +56,10 @@
<sec:logout logout-url="/c/logout" invalidate-session="true" logout-success-url="/c/login"/> <sec:logout logout-url="/c/logout" invalidate-session="true" logout-success-url="/c/login"/>
</sec:http> </sec:http>
<sec:authentication-manager alias="authenticationManager"> <!--<import resource="wisemapping-security-db.xml"/>-->
<sec:authentication-provider ref="dbAuthenticationProvider"/> <import resource="wisemapping-security-ldap.xml"/>
<sec:authentication-provider user-service-ref="userDetailsService"/>
</sec:authentication-manager>
<bean id="dbAuthenticationProvider" class="com.wisemapping.security.AuthenticationProvider">
<property name="userDetailsService" ref="userDetailsService"/>
<property name="encoder" ref="encoder"/>
</bean>
<bean id="userDetailsService" class="com.wisemapping.security.UserDetailsService"> <bean id="userDetailsService" class="com.wisemapping.security.UserDetailsService">
<!--suppress SpringModelInspection -->
<property name="userService" ref="userService"/> <property name="userService" ref="userService"/>
<property name="adminUser" value="${admin.user}"/> <property name="adminUser" value="${admin.user}"/>
</bean> </bean>
@ -76,4 +68,5 @@
<property name="defaultTargetUrl" value="/c/maps/"/> <property name="defaultTargetUrl" value="/c/maps/"/>
<property name="alwaysUseDefaultTargetUrl" value="false"/> <property name="alwaysUseDefaultTargetUrl" value="false"/>
</bean> </bean>
</beans> </beans>