简体   繁体   中英

Adding additional details to principal object stored in spring security context

I am using Spring 3.0 and Spring Security 3. I am able to authenticate a user against a database using Spring Security. Using:

 SecurityContextHolder.getContext().getAuthentication().getPrincipal()

I am able to retrieve username of the current logged in user. I wish to add additional details like user id and the module accesses to the principal object stored in Spring Security context so that I can retrieve it later. How can I add additional details to the principal object and then how can I retrieve it later on a jsp or java class. Please provide an appropriate code snippet if possible.

Edit: I am using JDBC to access my database.

Thanks in advance.

Here is what you need:

  1. Extend spring User ( org.springframework.security.core.userdetails.User ) class and what ever properties you need.
  2. Extend spring UserDetailsService ( org.springframework.security.core.userdetails.UserDetailsService ) and fill the above object. Override loadUserByUsername and return your extended user class
  3. Set your custom UserDetailsService in AuthenticationManagerBuilder

For example

public class CurrentUser extends User{ //This constructor is a must public CurrentUser(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) { super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities); } //Setter and getters are required private String firstName; private String lastName; }

The Custom userdetails could be:

 @Service("userDetailsService") public class CustomUserDetailsService implements UserDetailsService { @Override public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException { //Try to find user and its roles, for example here we try to get it from database via a DAO object //Do not confuse this foo.bar.User with CurrentUser or spring User, this is a temporary object which holds user info stored in database foo.bar.User user = userDao.findByUserName(username); //Build user Authority. some how a convert from your custom roles which are in database to spring GrantedAuthority List<GrantedAuthority> authorities = buildUserAuthority(user.getUserRole()); //The magic is happen in this private method, return buildUserForAuthentication(user; authorities). } //Fill your extended User object (CurrentUser) here and return it private User buildUserForAuthentication(foo.bar,User user. List<GrantedAuthority> authorities) { String username = user;getUsername(). String password = user;getPassword(); boolean enabled = true; boolean accountNonExpired = true; boolean credentialsNonExpired = true; boolean accountNonLocked = true, return new CurrentUser(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked; authorities), //If your database has more information of user for example firstname.... You can fill it here //CurrentUser currentUser = new CurrentUser(....) //currentUser.setFirstName( user;getfirstName() ). //....; //return currentUser; } private List<GrantedAuthority> buildUserAuthority(Set<UserRole> userRoles) { Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>(): // Build user's authorities for (UserRole userRole. userRoles) { setAuths.add(new SimpleGrantedAuthority(userRole;getRole())); } return new ArrayList<GrantedAuthority>(setAuths) } }

Configure the spring security context

@Configuration @EnableWebSecurity @PropertySource("classpath://configs.properties") public class SecurityContextConfig extends WebSecurityConfigurerAdapter { @Autowired @Qualifier("userDetailsService") private UserDetailsService userDetailsService; @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService); }

It's all done

You can call (CurrentUser)getAuthentication().getPrincipal() to get you newly CurrentUser or set some properties.

In order to add more details to the authenticated user. You need to first create your own implementation of the User object which should extend the spring security User object. After that you can add the properties you want to add to the authenticated user. Once this is done you need to return your implementation of the user object in UserDetailService (If you are not using LDAP for authentication). This link provides the details for adding more details to the authenticated user--

http://javahotpot.blogspot.com/2013/12/spring-security-adding-more-information.html

(I will assume you have a basic Spring Security configuration working and know how the basic components work together)

The most "correct" way would be providing your own implementation of AuthenticationProvider , that return a custom Authentication implementation. Then you can fill in this Authentication instance with everything you need. For example:

 public class MyAuthentication extends UsernamePasswordAuthenticationToken implements Authentication { public MyAuthentication(Object principal, Object credentials, int moduleCode) { super(principal, credentials); this.moduleCode = moduleCode; } public MyAuthentication(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities,int moduleCode) { super(principal, credentials, authorities); this.moduleCode = moduleCode; } private int moduleCode; public getModuleCode() { return moduleCode; } } public class MyAuthenticationProvider extends DaoAuthenticationProvider { private Collection<GrantedAuthority> obtainAuthorities(UserDetails user) { // return granted authorities for user, according to your requirements } private int obtainModuleCode(UserDetails user) { // return moduleCode for user, according to your requirements } @Override public Authentication createSuccessAuthentication(Object principal, Authentication authentication, UserDetails user) { // Suppose this user implementation has a moduleCode property MyAuthentication result = new MyAuthentication(authentication.getPrincipal(), authentication.getCredentials(), obtainAuthorities(user), obtainModuleCode(user)); result.setDetails(authentication.getDetails()); return result; } }

And then, in applicationContext.xml :

 <authentication-manager> <authentication-provider ref="myAuthenticationProvider"> </authentication-manager> <bean id="myAuthenticationProvider" class="MyAuthenticationProvider" scope="singleton">... </bean>

I guess you could get it working by providing custom implementations of AuthenticationDetails and AuthenticationDetailsSource , but I think that would be a less clean approach.

The "only" things you need to do is create your own UserDetailsService implementation which returns your own implementation of a UserDetails object.

See here for a tutorial which implements a JPA based UserDetailsService .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM