Announcement Announcement Module
Collapse
No announcement yet.
Setting parameters in a session scoped object while outside the session Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • 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)

  • #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?

    Comment


    • #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

      Comment


      • #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"

        Comment


        • #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, 12:17 AM.

          Comment


          • #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.

            Comment


            • #7
              Glad to hear you got it working, you beat me to it but yeah your end approach solution was the right one. Nice work!

              Comment


              • #8
                Originally posted by yabba View Post
                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.
                Hello yabba

                I got the same issue now,I followed your step but i still could not fix it out..((

                Comment


                • #9
                  Hi Ronald, I am not sure I am the best person to be helping with this issue as I am still not 100% sure of what I was doing wrong in the first place but see below for the code from my CustomUserDetailsService and CustomUserDetails classes which you might be able to use in trying to resolve the issue in your code.

                  CustomUserDetails:

                  package com.test.security;

                  import java.io.Serializable;
                  import java.util.Collection;
                  import java.util.Set;

                  import javax.inject.Named;

                  import org.springframework.context.annotation.Scope;
                  import org.springframework.security.core.GrantedAuthority ;
                  import org.springframework.security.core.userdetails.User ;
                  import org.springframework.security.core.userdetails.User Details;
                  import org.springframework.web.bind.annotation.SessionAtt ributes;

                  public class CustomUserDetails implements Serializable, UserDetails {

                  /**
                  *
                  */
                  private static final long serialVersionUID = 1L;
                  private String christianName;
                  private String surname;
                  private String username;
                  private String password;
                  private boolean accountNonExpired;
                  private boolean accountNonLocked;
                  private boolean credentialsNonExpired;
                  private boolean enabled;
                  private Set<String> roles;
                  private Set<String> privileges;
                  private Collection<? extends GrantedAuthority> authorities;

                  public UserProperties(String username, String password, boolean enabled,
                  boolean accountNonExpired, boolean credentialsNonExpired,
                  boolean accountNonLocked,
                  Collection<? extends GrantedAuthority> authorities) {

                  this.username = username;
                  this.password = password;
                  this.enabled = enabled;
                  this.accountNonExpired = accountNonExpired;
                  this.accountNonLocked = accountNonLocked;
                  this.credentialsNonExpired = credentialsNonExpired;
                  this.authorities = authorities;

                  }

                  public String getChristianName() {
                  return christianName;
                  }

                  public void setChristianName(String christianName) {
                  this.christianName = christianName;
                  }

                  public String getSurname() {
                  return surname;
                  }

                  public void setSurname(String surname) {
                  this.surname = surname;
                  }

                  public Set<String> getRoles() {
                  return roles;
                  }

                  public void setRoles(Set<String> roles) {
                  this.roles = roles;
                  }

                  public Set<String> getPrivileges() {
                  return privileges;
                  }

                  public void setPrivileges(Set<String> privileges) {
                  this.privileges = privileges;
                  }

                  @Override
                  public Collection<GrantedAuthority> getAuthorities() {
                  return (Collection<GrantedAuthority>) this.authorities;
                  }

                  @Override
                  public String getPassword() {
                  return this.password;
                  }

                  @Override
                  public String getUsername() {
                  return this.username;
                  }

                  @Override
                  public boolean isAccountNonExpired() {
                  return this.accountNonExpired;
                  }

                  @Override
                  public boolean isAccountNonLocked() {
                  return this.accountNonLocked;
                  }

                  @Override
                  public boolean isCredentialsNonExpired() {
                  return this.credentialsNonExpired;
                  }

                  @Override
                  public boolean isEnabled() {
                  return this.enabled;
                  }

                  public void setUsername(String username) {
                  this.username = username;
                  }

                  public void setPassword(String password) {
                  this.password = password;
                  }

                  public void setAccountNonExpired(boolean accountNonExpired) {
                  this.accountNonExpired = accountNonExpired;
                  }

                  public void setAccountNonLocked(boolean accountNonLocked) {
                  this.accountNonLocked = accountNonLocked;
                  }

                  public void setCredentialsNonExpired(boolean credentialsNonExpired) {
                  this.credentialsNonExpired = credentialsNonExpired;
                  }

                  public void setEnabled(boolean enabled) {
                  this.enabled = enabled;
                  }

                  public void setAuthorities(Collection<GrantedAuthority> authorities) {
                  this.authorities = authorities;
                  }

                  }

                  CustomUserDetailsService:

                  package com.test.web;

                  import org.slf4j.Logger;
                  import org.slf4j.LoggerFactory;
                  import org.springframework.beans.factory.annotation.Autow ired;
                  import org.springframework.dao.DataAccessException;
                  import org.springframework.security.core.userdetails.User Details;
                  import org.springframework.security.core.userdetails.User DetailsService;
                  import org.springframework.security.core.userdetails.User nameNotFoundException;
                  import org.springframework.stereotype.Service;

                  import com.test.security.CustomSecurityManager;

                  @Service("userDetailsService")
                  public class CustomUserDetailsService implements UserDetailsService {

                  private static final Logger logger = LoggerFactory.getLogger(ConcordUserDetailsService. class);

                  @Autowired
                  private UserService userService;

                  @Autowired
                  private CustomSecurityManager customSecurityManager;

                  @Autowired
                  private UserPropertiesService userPropertiesService;

                  @Override
                  public UserDetails loadUserByUsername(String username)
                  throws UsernameNotFoundException, DataAccessException {

                  User customUser = userService.getUserById(username);
                  customSecurityManager.populateUserProperties(custo mUser);
                  UserDetails user = userPropertiesService.getUserProperties();
                  return user;

                  }

                  }

                  Hopefully that helps a bit with your issue

                  Comment

                  Working...
                  X