-
Jul 13th, 2011, 09:05 PM
#1
Setting parameters in a session scoped object while outside the session
Hi All,
Hopefully someone can help me, or at least point me in the right direction. I have been working on this issue for 2 days now and have reached the point where I have no hair left to tear out.
My Setup:
Spring 3, using annotations.
Spring web mvc module using spring security
Hibernate persistence layer (perhaps not important to the issue being discussed)
My goal is to have a session scoped bean "UserProperties" that contains some information about the user currently logged into the system.
I have successfully created the session scoped bean.
@Scope("session")
@Named("userProperties")
public class UserProperties implements Serializable {
... bean properties
}
Using the following in the root context components of my webapp.
<bean id="userProperties" class="com.concord.security.UserProperties" scope="session">
<!-- This requires CGLIB -->
<aop:scoped-proxy/>
</bean>
I have a service "userPropertiesService" that I have setup to access the above bean.
I have a Manager class "SecurityManager" that i have autowired the "userPropertiesService" into in order to access the "UserProperties" bean from the session.
I have created a custom CustomSavedRequestAwareAuthenticationSuccessHandle r that extends the spring security SavedRequestAwareAuthenticationSuccessHandler. I have overridden the onAuthenticationSuccess method and Autowired the "SecurityManager" into it. I use the "SecurityManager" to call the "userPropertiesService" to get the bean from the session. Up to this point everything appears to work correctly. The Bean properties are changed and populated with data extracted from the hibernate layer based on the user who has logged in.
My problem comes when I try and access the bean in a controller. It tells me (everytime) that the bean is null. In order to access the bean I have Autowired in the "userPropertiesService" mentioned above, and called the "userPropertiesService.getUserProperties()" method (this is the same way i accessed the bean in the "CustomSavedRequestAwareAuthenticationSuccessHandl er").
From what I can see through my debug output. It appears that although the bean properties are changed through the CustomSavedRequestAwareAuthenticationSuccessHandle r, they are not persisted at this point in the session and that is why I cannot access them in the controller.
There is something else to note at this point. When I try and access the UserProperties from the controller they do not come back empty, they come back null, even though the UserProperties bean is instantiated during startup.
Perhaps I am doing something completely wrong, but I based my code on code in the link: http://wheelersoftware.com/articles/...ped-beans.html (its only 2 pages)
Thanks for your help (and taking the time to read this long issue)
-
Jul 14th, 2011, 10:21 AM
#2
Not totally sure I follow the issue. If I understand, you want to retrieve current information about the user from the session, which was stored upon login is that correct? If so did you try SecurityContext context = SecurityContextHolder.getContext() which gives you a handle on the current context including authorizations and the principal?
-
Jul 14th, 2011, 04:49 PM
#3
Thanks for your response TerpInMD and you are mostly correct in your interpretation of my question. I do want to get information stored about the user during logon. But what my ultimate goal is is that I would like to add extra information about the user during the login process and then access that information during the session.
Perhaps my approach is not correct. Could it be better to write a custom spring security "User" object that extends the default one and also contains my custom fields?
So essentially i could get the User (getPrincipal()) from the context and then call something like user.getMyCustomProperties() and have the properties I have stored during login.
Thanks again
-
Jul 14th, 2011, 09:26 PM
#4
An update:
I have done some googling and found a few places that detail how to write a custom UserDetails object and UserDetailsService, which I have implemented. I have now run into an entirely separate issue. Every time I login (with correct credentials) the custom UserDetailsService is used and the custom UserDetails object is populated, however, the user no longer authenticates... When I access the principal from the SecurityContext it comes back with "annonymousUser"
-
Jul 15th, 2011, 12:06 AM
#5
Another update:
I have created the following custom UserDetailsService:
@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserService userService;
@Autowired
private MyManager myManager;
@Autowired
private UserPropertiesService userPropertiesService;
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException {
UserEntity userEntity = userService.getUserById(username);
myManager.populateUserProperties(userEntity);
UserProperties userProperties = userPropertiesService.getUserProperties();
Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
//authorities.add(new GrantedAuthorityImpl("ROLE_USER"));
/* THESE 2 LINES ARE VERY IMPORTANT TO MY QUESTION */
//User user = new User(concordUser.getId(), concordUser.getPassword(), concordUser.isEnabled(), true, true, true, authorities);
User user = userPropertiesService.getUserProperties();
return user;
}
}
I also have a UserProperties which extends Spring Securities "User"
public class UserProperties extends User implements Serializable {
public UserProperties(String username, String password, boolean enabled,
boolean accountNonExpired, boolean credentialsNonExpired,
boolean accountNonLocked,
Collection<? extends GrantedAuthority> authorities) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired,
accountNonLocked, authorities);
}
}
My custom UserDetails Service populates my custom UserProperties with information about a user that I have obtained from my database. Up to this point everything works perfectly. I have a reference to the userDetailsService in my context.xml as follows:
<security:authentication-provider user-service-ref="userDetailsService"/>
In my custom UserDetailsService, you will notice at the bottom the comment "/* THESE 2 LINES ARE VERY IMPORTANT TO MY QUESTION */". If I use the line just below that that is currently commented out, my user is authenticated but I only have a standard spring User object created. And i get the following output in my logs:
TRACE: org.springframework.web.context.support.XmlWebAppl icationContext - Publishing event in Root WebApplicationContext: org.springframework.security.authentication.event. AuthenticationSuccessEvent[source=org.springframework.security.authentication .UsernamePasswordAuthenticationToken@fffe7019: Principal: org.springframework.security.core.userdetails.User @e3d: Username: t1; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Not granted any authorities; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.We bAuthenticationDetails@0: RemoteIpAddress: 127.0.0.1; SessionId: C38100A3E2DFD34328A003BCADC50234; Not granted any authorities]
If i use the line "User user = userPropertiesService.getUserProperties();" in which i call the super method of the spring User object i get the following output in my debug:
DEBUG: org.springframework.security.authentication.dao.Da oAuthenticationProvider - User account is locked
TRACE: org.springframework.web.context.support.XmlWebAppl icationContext - Publishing event in Root WebApplicationContext: org.springframework.security.authentication.event. AuthenticationFailureLockedEvent[source=org.springframework.security.authentication .UsernamePasswordAuthenticationToken@fffc9b48: Principal: t1; Credentials: [PROTECTED]; Authenticated: false; Details: org.springframework.security.web.authentication.We bAuthenticationDetails@fffd148a: RemoteIpAddress: 127.0.0.1; SessionId: 8D99744373F2BF4C60562B43EBABD088; Not granted any authorities]
If you notice the "Principal" from both of those trace outputs, in the scenario that authenticates this is a UserObject, however, in the failed scenario it is just a string with the username.
Is there something that I have done completely wrong? I am trying to access the system with the same credentials.
Last edited by yabba; Jul 15th, 2011 at 12:17 AM.
-
Jul 15th, 2011, 01:01 AM
#6
Resolved:
I have managed to resolve the problem, although I am not sure exactly why it was a problem in the first place...
I changed my custom UserDetails class back to a class that implements UserDetails rather than extends springs standard User object. (I had tried this earlier today with no luck).
I also changed the constructor for the class paying particular attention to the Collection of granted authorities.
When declaring this variable in the custom object i had originally declared:
private Collection<GrantedAuthority> authorities;
however, what i needed to declare was:
private Collection<? extends GrantedAuthority> authorities;
Changing that declaration, and the corresponding getter resolved the issue.
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules