Acegi Security uses the SecurityContextHolder object to store details of the current security context of the application. The SecurityContext holds the details of the authenticated principal in an Authentication object. By default the SecurityContextHolder uses a ThreadLocal to store these details, so that they will be available all methods in the current thread of execution.In order to obtain the Principal, you would use the following line
Object obj = SecurityContextHolder.getContext().getAuthentication().getPrincipal();Usually, the principal is an object of the type UserDetails. The UserDetails object is sort of an adapter between the security database and Acegi SecurityContextHolder. Acegi uses a UserDetailsSevice to build the UserDetails object. In order to modify the data stored Security Context of Acegi, you either have to
- setContext() method of the SecurityContextHolder. The SecurityContext object can be set to hold an Authentication object. This will mean that you have to add some additional security code to your application code.
- Implement the UserDetailsService and UserDetails interfaces. This way you can keep security code seperated from the application code.
- Start with the implementing acegi security posts part 1 and part 2.
- Create the UserDetailsService:
package authentication;
import java.util.HashMap;
import java.util.Map;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.userdetails.UserDetails;
import org.acegisecurity.userdetails.UserDetailsService;
import org.acegisecurity.userdetails.UsernameNotFoundException;
import org.springframework.dao.DataAccessException;
public class MyUserDetailsService implements UserDetailsService {
private Map users = init();
private Map init() {
Map tUsers = new HashMap();
tUsers.put("scott", new User("scott", "tiger", "ROLE_USER"));
tUsers.put("harry", new User("harry", "potter", "ROLE_ADMIN"));
tUsers.put("frodo", new User("frodo", "baggins", "ROLE_USER"));
return tUsers;
}
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException, DataAccessException {
User user = (User) users.get(s);
GrantedAuthority authority = new MyGrantedAuthority(user.getRole());
UserDetails userDetails = new MyUserDetails(new GrantedAuthority[] { authority }, user.getUserId(), user.getPassword(), "Additional Data");
return userDetails;
}
}MyUserDetailsService.java
Notice that all the user data is defined in this class. The UserDetailsService has to return a UserDetails object using the User name. - Create the UserDetails class:
package authentication;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.userdetails.UserDetails;
public class MyUserDetails implements UserDetails {
private GrantedAuthority[] authorities = null;
private String password = null;
private String username = null;
private String additionalData = null;
public MyUserDetails(GrantedAuthority[] authorities, String password, String username, String additionalData) {
super();
this.authorities = authorities;
this.password = password;
this.username = username;
this.additionalData = additionalData;
}
public GrantedAuthority[] getAuthorities() {
return authorities;
}
public String getPassword() {
return password;
}
public String getUsername() {
return username;
}
public boolean isAccountNonExpired() {
return true;
}
public boolean isAccountNonLocked() {
return true;
}
public boolean isCredentialsNonExpired() {
return true;
}
public boolean isEnabled() {
return true;
}
}MyUserDetails.java - The User class:
package authentication;
public class User {
private String userId;
private String password;
private String role;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public User(String userId, String password, String role) {
super();
this.userId = userId;
this.password = password;
this.role = role;
}
}User.java - Modify the applicationContext.xml file: Modify the userDetailsService bean in the application context to as shown below
<bean id="userDetailsService" class="authentication.MyUserDetailsService">
</bean> - The GrantedAuthority class: The MyGrantedAuthority class is typically used to store application roles.
package authentication;
import org.acegisecurity.GrantedAuthority;
public class MyGrantedAuthority implements GrantedAuthority {
private String authority = null;
public MyGrantedAuthority(String authority) {
this.authority = authority;
}
public String getAuthority() {
return authority;
}
}MyGrantedAuthority.java