0

I'm using Spring Security to handle user authentication for my Spring MVC web app. I'm able to get the username from the Authentication object, but my username is the email address, and I want to be able to show the user's actual name in my header.

So I have my custom User class:

class Users{

    String name;
    String email;
    String password;

    // getters and setters
}

I thought about using an aop scoped proxy to set the User in the session, as explained in this blog: http://richardchesterwood.blogspot.co.uk/2011/03/using-sessions-in-spring-mvc-including.html . The problem I faced using this approach is that the AuthenticationSuccessHandler is actually a Service and should be stateless. So Spring doesn't autowire a Users object for me in the Service.

So I created a Service method that would get the username (or email) from the Authentication object and return my Users object. This I can use in my Controllers.

@Service
@Transactional
public class UserServiceImpl implements UserService {

@Override
public Users getCurrentUser() {
     Authentication auth = SecurityContextHolder.getContext().getAuthentication();

    User userD = (User)auth.getPrincipal();

    Users currentUser = getUserByEmail(userD.getUsername());

    return currentUser;
}

}

So is there a way that I can call this Service method from JSTL to get the user's full name, which I can display in my header?

Am also open to suggestions for a better way to implement this.

EDIT:

In my earlier approach using the AuthenticationSuccessHandler, my code goes like this:

@Service("userDetailsService")
@Transactional
public class UserAuthenticationServiceImpl implements AuthenticationSuccessHandler {

@Autowired
Users currentUser;

@Override
public void onAuthenticationSuccess(HttpServletRequest hsr, HttpServletResponse hsr1, Authentication a) throws IOException, ServletException {
    User user = (User) a.getPrincipal();

    Users user1 = userDao.getUserByEmail(user.getUsername());

    currentUser.setName(user1.getName());
    currentUser.setUserRoles(user1.getUserRoles());

    //currentUser = user1;

}

}

And in my spring-servlet.xml file, I have this:

<bean id="currentUser" class="com.foo.bean.Users" scope="session">
    <!-- this next element effects the proxying of the surrounding bean -->
    <aop:scoped-proxy/>
</bean>

The problem I'm facing here is that Spring isn't autowiring my currentUser object because the Service isn't in the session scope.

Anand Sriraman
  • 158
  • 1
  • 8
  • Create a custom `User` instead of the default one from Spring Security which includes this information and just modify the expression. You shouldn't be doing it like what you have now, you don't want that additional query and complexity each time a page is rendered. – M. Deinum May 19 '15 at 10:09
  • Thanks Deinum. Where do I tell Spring Security to use my custom User class instead? – Anand Sriraman May 19 '15 at 10:13
  • On second thought, if you already have an `AuthenticationSuccessHandler` why not simply use that to get the information you need and store it in the session. You have everything you need to accomplish that in that method. – M. Deinum May 19 '15 at 10:17
  • I've updated my question detailing my approach using the AuthenticationSuccessHandler. – Anand Sriraman May 19 '15 at 10:29
  • 1
    Don't do it like that. Just put in the session. `WebUtils.setSessionAttribute(request, "currentUser", user1);` then in your page you can simply do `${currentUser.username}`. You are thinking to complex. Adding the full user to the session might be a bit of an overkill, you can just put the name in there is probably a whole lot lighter then the whole object. – M. Deinum May 19 '15 at 10:34
  • Ah! I did not know about WebUtils. Thanks a bunch! Could you add it as an answer so that I can mark it as such? – Anand Sriraman May 19 '15 at 10:36
  • 1
    That is just a nice helper `request.getSession().setAttribute("currentUser", user1)` yields the same result. – M. Deinum May 19 '15 at 10:37

1 Answers1

1

If the only thing you need is the full name just use an AuthenticationSuccessHandler to retrieve the user and add the name to the session (or the full user if you need more then that).

@Override
public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse res, Authentication auth) throws IOException, ServletException {

    User user = (User) auth.getPrincipal();
    Users user1 = userDao.getUserByEmail(user.getUsername());
    WebUtils.setSessionAttribute(req, "currentUser" user1);
}

Then in your JSP the only thing you need is ${currentUser.username}.

Although I wouldn't suggest stuffing the full user in the session I would suggest just adding the information needed.

WebUtils.setSessionAttribute(req, "currentUsername" user1.getUsername());

Then in your JSP ${currentUsername} saves you a lot of serialization overhead of the session.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224