Skip to content

Instantly share code, notes, and snippets.

@raj23manj
Forked from esfand/customdao.md
Created December 29, 2018 10:43
Show Gist options
  • Select an option

  • Save raj23manj/774d71ca2f13b2061c0e31634ac21be4 to your computer and use it in GitHub Desktop.

Select an option

Save raj23manj/774d71ca2f13b2061c0e31634ac21be4 to your computer and use it in GitHub Desktop.

Revisions

  1. @esfand esfand revised this gist Oct 3, 2013. 2 changed files with 32 additions and 29 deletions.
    58 changes: 31 additions & 27 deletions customdao.md
    Original file line number Diff line number Diff line change
    @@ -95,28 +95,32 @@ in authentication-provider tag.
    <!-- this is security configuration file which maps urls according to user roles authorization -->
    <security:http auto-config="true">
    <security:logout logout-success-url="/login" invalidate-session="true" logout-url="/logout"/>
    <security:intercept-url pattern="/login.jsp" filters="none" />
    <security:intercept-url pattern="/login" filters="none" />
    <security:intercept-url pattern="/logout" filters="none" />
    <security:intercept-url pattern="/Test" access="ROLE_ADMIN" />
    <security:intercept-url pattern="/home" access="ROLE_ADMIN,ROLE_USER"/>
    <security:intercept-url pattern="/user/*" access="ROLE_USER" />
    <security:intercept-url pattern="/admin/*" access="ROLE_ADMIN" />
    <security:intercept-url pattern="/*" filters="none"/>
    <security:form-login login-page="/login"
    default-target-url="/home" authentication-failure-url="/login?error=1"
    always-use-default-target="true"/>
    </security:http>
    <security:authentication-provider
    user-service-ref="userDetailsService" />
    <bean id='userDetailsService' class='com.security.UserDetailServiceImpl'>
    <property name='userdao' ref='userDao' />
    </bean>
    <security:http auto-config="true">
    <security:logout logout-success-url="/login"
    invalidate-session="true"
    logout-url="/logout" />
    <security:intercept-url pattern="/login.jsp" filters="none" />
    <security:intercept-url pattern="/login" filters="none" />
    <security:intercept-url pattern="/logout" filters="none" />
    <security:intercept-url pattern="/Test" access="ROLE_ADMIN" />
    <security:intercept-url pattern="/home" access="ROLE_ADMIN,ROLE_USER"/>
    <security:intercept-url pattern="/user/*" access="ROLE_USER" />
    <security:intercept-url pattern="/admin/*" access="ROLE_ADMIN" />
    <security:intercept-url pattern="/*" filters="none"/>
    <security:form-login login-page="/login"
    default-target-url="/home"
    authentication-failure-url="/login?error=1"
    always-use-default-target="true"/>
    </security:http>
    <security:authentication-provider user-service-ref="userDetailsService" />
    <bean id='userDetailsService' class='com.security.UserDetailServiceImpl'>
    <property name='userdao' ref='userDao' />
    </bean>
    </beans>
    ~~~~
    @@ -151,7 +155,11 @@ import com.model.UserRoles;
    import com.util.CustomLogger;
    /**
    * home controller redirects the user based on the roles
    * home controller to redirect users based on their role.
    * this is the home controller to redirect user to their home pages based on role name
    * * for admin it should be /admin/home
    * * for user it should be /user/home
    *
    * @author abhishek.somani
    */
    public class HomeController extends AbstractController {
    @@ -160,10 +168,6 @@ public class HomeController extends AbstractController {
    protected ModelAndView handleRequestInternal(HttpServletRequest request,
    HttpServletResponse arg1)
    throws Exception {
    // this is the home controller to redirect user to their home pages based on role name
    // for admin it should be /admin/home
    // for user it should be /user/home
    if (request.isUserInRole("ROLE_USER")) {
    request.setAttribute("appendURL", "user");
    return new ModelAndView("user/home", "welcome ", null);
    3 changes: 1 addition & 2 deletions customuserdetails.md
    Original file line number Diff line number Diff line change
    @@ -2,8 +2,7 @@

    [Source](http://stackoverflow.com/questions/10607696/spring-security-custom-userdetails)

    I'm pretty new to Java and Spring 3 (used primarily PHP the past 8 years).
    I've gotten spring security 3 to work with all the default userDetails and
    I've gotten spring security 3 to work with all the default userDetails and
    userDetailsService and I know I can access the logged in user's username in
    a controller by using:

  2. @esfand esfand revised this gist Oct 3, 2013. 1 changed file with 64 additions and 66 deletions.
    130 changes: 64 additions & 66 deletions customdao.md
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,7 @@
    ## How to use Custom DAO class in Spring Security

    [Source](http://www.javaroots.com/2013/03/how-to-use-custom-dao-classe-in-spring.html)

    * Objective 1 : Use Custom DAO classes in Spring Security Spring Security provides
    mechanism by which we can specify database queries in spring security xml file ,
    but sometimes we want to use our own custom dao classes which are already built.
    @@ -24,54 +26,55 @@ import com.dal.interfaces.UserDAO;
    import com.exceptions.DAOException;
    /**
    * //this class is used by spring controller to authenticate and authorize user
    * This class is used by spring controller to authenticate and authorize user
    * modified this class to user our Database and defined user roles
    *
    * @author abhishek.somani
    *
    */
    public class UserDetailServiceImpl implements UserDetailsService {
    private UserDAO userdao;
    public void setUserdao(UserDAO userdao) {
    this.userdao = userdao;
    }
    // this class is used by spring controller to authenticate and authorize
    // user
    @Override
    public UserDetails loadUserByUsername(String userId)
    throws UsernameNotFoundException {
    com.model.User u;
    try {
    u = userdao.get(userId);
    if (u == null)
    throw new UsernameNotFoundException("user name not found");
    } catch (DAOException e) {
    throw new UsernameNotFoundException("database error ");
    }
    return buildUserFromUserEntity(u);
    }
    private User buildUserFromUserEntity(com.model.User userEntity) {
    // convert model user to spring security user
    String username = userEntity.getUserId();
    String password = userEntity.getPassword();
    boolean enabled = true;
    boolean accountNonExpired = true;
    boolean credentialsNonExpired = true;
    boolean accountNonLocked = true;
    GrantedAuthority[] authorities = new GrantedAuthorityImpl[1];
    authorities[0] = new GrantedAuthorityImpl(userEntity.getRole());
    User springUser = new User(username, password, enabled,
    accountNonExpired, credentialsNonExpired, accountNonLocked,
    authorities);
    return springUser;
    }
    private UserDAO userdao;
    public void setUserdao(UserDAO userdao) {
    this.userdao = userdao;
    }
    // this class is used by spring controller to authenticate and authorize user
    @Override
    public UserDetails loadUserByUsername(String userId)
    throws UsernameNotFoundException {
    com.model.User u;
    try {
    u = userdao.get(userId);
    if (u == null)
    throw new UsernameNotFoundException("user name not found");
    } catch (DAOException e) {
    throw new UsernameNotFoundException("database error ");
    }
    return buildUserFromUserEntity(u);
    }
    private User buildUserFromUserEntity(com.model.User userEntity) {
    // convert model user to spring security user
    String username = userEntity.getUserId();
    String password = userEntity.getPassword();
    boolean enabled = true;
    boolean accountNonExpired = true;
    boolean credentialsNonExpired = true;
    boolean accountNonLocked = true;
    GrantedAuthority[] authorities = new GrantedAuthorityImpl[1];
    authorities[0] = new GrantedAuthorityImpl(userEntity.getRole());
    User springUser = new User(username,
    password,
    enabled,
    accountNonExpired,
    credentialsNonExpired,
    accountNonLocked,
    authorities);
    return springUser;
    }
    }
    ~~~~

    @@ -150,32 +153,27 @@ import com.util.CustomLogger;
    /**
    * home controller redirects the user based on the roles
    * @author abhishek.somani
    *
    */
    public class HomeController extends AbstractController
    {
    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest request,HttpServletResponse arg1) throws Exception
    {
    //this is the home controller to redirect user to their home pages based on role name
    // for Admin it should be /admin/home
    //for user it should be /user/home
    public class HomeController extends AbstractController {
    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest request,
    HttpServletResponse arg1)
    throws Exception {
    // this is the home controller to redirect user to their home pages based on role name
    // for admin it should be /admin/home
    // for user it should be /user/home
    if (request.isUserInRole("ROLE_USER"))
    {
    request.setAttribute("appendURL", "user");
    return new ModelAndView("user/home", "welcome ", null);
    }
    if (request.isUserInRole("ROLE_ADMIN"))
    {
    request.setAttribute("appendURL", "admin");
    return new ModelAndView("admin/home", "welcome ", null);
    }
    throw new Exception("No roles Detected");
    }
    if (request.isUserInRole("ROLE_USER")) {
    request.setAttribute("appendURL", "user");
    return new ModelAndView("user/home", "welcome ", null);
    }
    if (request.isUserInRole("ROLE_ADMIN")) {
    request.setAttribute("appendURL", "admin");
    return new ModelAndView("admin/home", "welcome ", null);
    }
    throw new Exception("No roles Detected");
    }
    }
    ~~~~

  3. @esfand esfand revised this gist Oct 3, 2013. 2 changed files with 184 additions and 1 deletion.
    181 changes: 181 additions & 0 deletions customdao.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,181 @@
    ## How to use Custom DAO class in Spring Security

    * Objective 1 : Use Custom DAO classes in Spring Security Spring Security provides
    mechanism by which we can specify database queries in spring security xml file ,
    but sometimes we want to use our own custom dao classes which are already built.
    * Objective 2 : Forward the request to different home pages based on the authorized
    role


    First , to use your custom dao class , we have to create a bean which implements `org.springframework.security.userdetails.UserDetailsService` interface.
    Override the loadUserByUserName method of this interface. We have to create
    `org.springframework.security.userdetails.User` from our custom dao object.

    ~~~~
    package com.security;
    import org.springframework.security.GrantedAuthority;
    import org.springframework.security.GrantedAuthorityImpl;
    import org.springframework.security.userdetails.User;
    import org.springframework.security.userdetails.UserDetails;
    import org.springframework.security.userdetails.UserDetailsService;
    import org.springframework.security.userdetails.UsernameNotFoundException;
    import com.dal.interfaces.UserDAO;
    import com.exceptions.DAOException;
    /**
    * //this class is used by spring controller to authenticate and authorize user
    * modified this class to user our Database and defined user roles
    *
    * @author abhishek.somani
    *
    */
    public class UserDetailServiceImpl implements UserDetailsService {
    private UserDAO userdao;
    public void setUserdao(UserDAO userdao) {
    this.userdao = userdao;
    }
    // this class is used by spring controller to authenticate and authorize
    // user
    @Override
    public UserDetails loadUserByUsername(String userId)
    throws UsernameNotFoundException {
    com.model.User u;
    try {
    u = userdao.get(userId);
    if (u == null)
    throw new UsernameNotFoundException("user name not found");
    } catch (DAOException e) {
    throw new UsernameNotFoundException("database error ");
    }
    return buildUserFromUserEntity(u);
    }
    private User buildUserFromUserEntity(com.model.User userEntity) {
    // convert model user to spring security user
    String username = userEntity.getUserId();
    String password = userEntity.getPassword();
    boolean enabled = true;
    boolean accountNonExpired = true;
    boolean credentialsNonExpired = true;
    boolean accountNonLocked = true;
    GrantedAuthority[] authorities = new GrantedAuthorityImpl[1];
    authorities[0] = new GrantedAuthorityImpl(userEntity.getRole());
    User springUser = new User(username, password, enabled,
    accountNonExpired, credentialsNonExpired, accountNonLocked,
    authorities);
    return springUser;
    }
    }
    ~~~~

    In Spring-security.xml we have to give reference of this bean in user-service-ref
    in authentication-provider tag.

    ~~~~
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:security="http://www.springframework.org/schema/security"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-2.0.1.xsd
    http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    <!-- this is security configuration file which maps urls according to user roles authorization -->
    <security:http auto-config="true">
    <security:logout logout-success-url="/login" invalidate-session="true" logout-url="/logout"/>
    <security:intercept-url pattern="/login.jsp" filters="none" />
    <security:intercept-url pattern="/login" filters="none" />
    <security:intercept-url pattern="/logout" filters="none" />
    <security:intercept-url pattern="/Test" access="ROLE_ADMIN" />
    <security:intercept-url pattern="/home" access="ROLE_ADMIN,ROLE_USER"/>
    <security:intercept-url pattern="/user/*" access="ROLE_USER" />
    <security:intercept-url pattern="/admin/*" access="ROLE_ADMIN" />
    <security:intercept-url pattern="/*" filters="none"/>
    <security:form-login login-page="/login"
    default-target-url="/home" authentication-failure-url="/login?error=1"
    always-use-default-target="true"/>
    </security:http>
    <security:authentication-provider
    user-service-ref="userDetailsService" />
    <bean id='userDetailsService' class='com.security.UserDetailServiceImpl'>
    <property name='userdao' ref='userDao' />
    </bean>
    </beans>
    ~~~~

    Now we want to redirect user after authentication and authorization by user.

    * If a user has **User role** , it should go to home page of user, or
    * if a user has **admin role** then it should go to home page of admin .

    For this , create a simple controller. After successfull authorization and
    authentication `request.getUserPrinicipal` will have the **Prinicipal object**
    containing `userName` which is set in `UserDetailServiceImpl` and we can
    check the roles by `request.isUserInRole` method.

    In spring-security.xml , set target url to this controller and set
    always-use-default-target attribute to true in form-login tag , because we
    always want this controller to execute after user successfully authenticate
    the user. Sometimes if the request contains referer header, spring security
    redirect it to that previous link.That is why we set always-use-default-target
    attribute to true.

    ~~~~
    package com.controller;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.apache.log4j.Logger;
    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.mvc.AbstractController;
    import com.constants.Constants;
    import com.model.UserRoles;
    import com.util.CustomLogger;
    /**
    * home controller redirects the user based on the roles
    * @author abhishek.somani
    *
    */
    public class HomeController extends AbstractController
    {
    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest request,HttpServletResponse arg1) throws Exception
    {
    //this is the home controller to redirect user to their home pages based on role name
    // for Admin it should be /admin/home
    //for user it should be /user/home
    if (request.isUserInRole("ROLE_USER"))
    {
    request.setAttribute("appendURL", "user");
    return new ModelAndView("user/home", "welcome ", null);
    }
    if (request.isUserInRole("ROLE_ADMIN"))
    {
    request.setAttribute("appendURL", "admin");
    return new ModelAndView("admin/home", "welcome ", null);
    }
    throw new Exception("No roles Detected");
    }
    }
    ~~~~

    4 changes: 3 additions & 1 deletion customuserdetails.md
    Original file line number Diff line number Diff line change
    @@ -80,7 +80,9 @@ login.jsp:
    <td>
    <input type='text'
    name='j_username'
    value='<c:if test="${not empty param.login_error}"><c:out value="${SPRING_SECURITY_LAST_USERNAME}"/></c:if>' />
    value='<c:if test="${not empty param.login_error}">
    <c:out value="${SPRING_SECURITY_LAST_USERNAME}"/>
    </c:if>' />
    </td>
    </tr>
    <tr>
  4. @esfand esfand revised this gist Oct 3, 2013. 1 changed file with 3 additions and 4 deletions.
    7 changes: 3 additions & 4 deletions customuserdetails.md
    Original file line number Diff line number Diff line change
    @@ -140,10 +140,9 @@ There are a couple possible approaches here.
    If you want to retrieve the domain-specific user/account, you can do so as follows:

    ~~~~
    User user = userDao.getByUsername(SecurityContextHolder
    .getContext()
    .getAuthentication()
    .getName());
    User user = userDao.getByUsername(SecurityContextHolder.getContext()
    .getAuthentication()
    .getName());
    ~~~~

    ## Q#2:
  5. @esfand esfand revised this gist Oct 3, 2013. 2 changed files with 6 additions and 0 deletions.
    4 changes: 4 additions & 0 deletions customuserdetails.md
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,7 @@
    ## Spring Security: custom userdetails

    [Source](http://stackoverflow.com/questions/10607696/spring-security-custom-userdetails)

    I'm pretty new to Java and Spring 3 (used primarily PHP the past 8 years).
    I've gotten spring security 3 to work with all the default userDetails and
    userDetailsService and I know I can access the logged in user's username in
    2 changes: 2 additions & 0 deletions userid.md
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,7 @@
    ## Retrieving unique user data in Spring Security

    [Source](http://stackoverflow.com/questions/9716442/retrieving-unique-user-data-in-spring-security)

    I have a table of items, user should be able to choose some of them, then these items
    are put in the other table (in the second table they are associated with the user who
    chose the items). I could associate items and users with a help of usernames, but
  6. @esfand esfand revised this gist Oct 3, 2013. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion userid.md
    Original file line number Diff line number Diff line change
    @@ -33,7 +33,9 @@ public class CustomUserDetailService implements UserDetailsService{
    private IUserDao userDao;
    @Override
    public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException, DataAccessException {
    public UserDetails loadUserByUsername(String name)
    throws UsernameNotFoundException,
    DataAccessException {
    User user = userDao.loadByName(name);
    CustomUserDetail customUserDetail = new CustomUserDetail();
    customUserDetail.setId(user.getId());
  7. @esfand esfand revised this gist Oct 3, 2013. 1 changed file with 47 additions and 0 deletions.
    47 changes: 47 additions & 0 deletions userid.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,47 @@
    ## Retrieving unique user data in Spring Security

    I have a table of items, user should be able to choose some of them, then these items
    are put in the other table (in the second table they are associated with the user who
    chose the items). I could associate items and users with a help of usernames, but
    I suppose it wouldn't be great. I wonder, what is a good way to do that.

    I know there is an easy way to retrieve the username
    (`<sec:authentication property="principal.username"/>`), but today I learnt there is
    no such a way for an id.

    * What is a good way to solve this problem?
    * Should I implement UserDetails to have an opportunity to get each id?
    * Is there any good example of this implementation? I use Hibernate to
    communicate with the database.
    * Is there any other way of the identification (compound key consisted of values that
    are easy to retrieve or something like that)?


    ### Answer

    Yes you have to implement your own UserDetail which will have an id attribute.

    You'll then fill in this object during authentication in your implementation of UserDetailService.

    For example:

    ~~~~
    @Service("CustomUserDetailService")
    public class CustomUserDetailService implements UserDetailsService{
    @Autowired
    private IUserDao userDao;
    @Override
    public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException, DataAccessException {
    User user = userDao.loadByName(name);
    CustomUserDetail customUserDetail = new CustomUserDetail();
    customUserDetail.setId(user.getId());
    customUserDetail.setPassword(user.getPassword());
    return customUserDetail ;
    }
    ~~~~

    After that you can retrieve anything from your principal :

    <sec:authentication property="principal.id"/>
  8. @esfand esfand revised this gist Oct 3, 2013. 1 changed file with 4 additions and 1 deletion.
    5 changes: 4 additions & 1 deletion customuserdetails.md
    Original file line number Diff line number Diff line change
    @@ -136,7 +136,10 @@ There are a couple possible approaches here.
    If you want to retrieve the domain-specific user/account, you can do so as follows:

    ~~~~
    User user = userDao.getByUsername(SecurityContextHolder.getContext().getAuthentication().getName());
    User user = userDao.getByUsername(SecurityContextHolder
    .getContext()
    .getAuthentication()
    .getName());
    ~~~~

    ## Q#2:
  9. @esfand esfand revised this gist Oct 3, 2013. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions customuserdetails.md
    Original file line number Diff line number Diff line change
    @@ -135,7 +135,9 @@ There are a couple possible approaches here.

    If you want to retrieve the domain-specific user/account, you can do so as follows:

    ~~~~
    User user = userDao.getByUsername(SecurityContextHolder.getContext().getAuthentication().getName());
    ~~~~

    ## Q#2:

  10. @esfand esfand revised this gist Oct 3, 2013. 1 changed file with 3 additions and 2 deletions.
    5 changes: 3 additions & 2 deletions customuserdetails.md
    Original file line number Diff line number Diff line change
    @@ -131,8 +131,9 @@ There are a couple possible approaches here.
    Spring Security specific user/account details. This may or may not be the case for you.
    But if you can find any wisdom in this approach, then you'd stick with the setup you
    have currently and add an additional User/Account domain object, corresponding
    repository/DAO, etc. If you want to retrieve the domain-specific user/account, you
    can do so as follows:
    repository/DAO, etc.

    If you want to retrieve the domain-specific user/account, you can do so as follows:

    User user = userDao.getByUsername(SecurityContextHolder.getContext().getAuthentication().getName());

  11. @esfand esfand revised this gist Oct 3, 2013. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions customuserdetails.md
    Original file line number Diff line number Diff line change
    @@ -16,8 +16,8 @@ my custom fields?**
    I'm already calling `HttpSession session = request.getSession(true);` at the top
    of each of my methods in my controller.

    * **Is it possible to store the logged in user's userDetails in a session upon
    login so that I don't need to also call
    * **Is it possible to store the logged in user's userDetails in a session
    upon login so that I don't need to also call
    `Authentication auth = SecurityContextHolder.getContext().getAuthentication();`
    at the beginning of every method?**

  12. @esfand esfand revised this gist Oct 3, 2013. 1 changed file with 62 additions and 17 deletions.
    79 changes: 62 additions & 17 deletions customuserdetails.md
    Original file line number Diff line number Diff line change
    @@ -16,8 +16,8 @@ my custom fields?**
    I'm already calling `HttpSession session = request.getSession(true);` at the top
    of each of my methods in my controller.

    * **Is it possible to store the logged in
    user's userDetails in a session upon login so that I don't need to also call
    * **Is it possible to store the logged in user's userDetails in a session upon
    login so that I don't need to also call
    `Authentication auth = SecurityContextHolder.getContext().getAuthentication();`
    at the beginning of every method?**

    @@ -45,7 +45,8 @@ Security-applicationContext.xml:
    <authentication-provider>
    <jdbc-user-service data-source-ref="dataSource"
    authorities-by-username-query=
    "SELECT U.username, UR.authority, U.userid FROM users U, userroles UR WHERE U.username=? AND U.roleid=UR.roleid LIMIT 1" />
    "SELECT U.username, UR.authority, U.userid FROM users U, userroles UR
    WHERE U.username=? AND U.roleid=UR.roleid LIMIT 1" />
    <password-encoder hash="md5"/>
    </authentication-provider>
    </authentication-manager>
    @@ -65,27 +66,50 @@ login.jsp:
    <h1>Login</h1>
    <c:if test="${not empty param.login_error}">
    <font color="red"><c:out value="${SPRING_SECURITY_LAST_EXCEPTION.message}"/>.<br /><br /></font>
    <font color="red"><c:out value="${SPRING_SECURITY_LAST_EXCEPTION.message}"/>.
    <br/><br /></font>
    </c:if>
    <form name="f" action="<c:url value='/loginProcess'/>" method="POST">
    <table>
    <tr><td>User:</td><td><input type='text' name='j_username' value='<c:if test="${not empty param.login_error}"><c:out value="${SPRING_SECURITY_LAST_USERNAME}"/></c:if>' /></td></tr>
    <tr><td>Password:</td><td><input type='password' name='j_password' /></td></tr>
    <tr><td>&nbsp;</td><td><input type="checkbox" name="_spring_security_remember_me" /> Remember Me</td></tr>
    <tr><td>&nbsp;</td><td><input name="submit" type="submit" value="Login" /></td></tr>
    </table>
    </form>
    ~~~~
    <tr>
    <td>User:</td>
    <td>
    <input type='text'
    name='j_username'
    value='<c:if test="${not empty param.login_error}"><c:out value="${SPRING_SECURITY_LAST_USERNAME}"/></c:if>' />
    </td>
    </tr>
    <tr>
    <td>Password:</td>
    <td><input type='password' name='j_password' /></td>
    </tr>
    <tr>
    <td>&nbsp;</td>
    <td><input type="checkbox" name="_spring_security_remember_me" /> Remember Me</td>
    </tr>
    <tr>
    <td>&nbsp;</td>
    <td><input name="submit" type="submit" value="Login" /></td>
    </tr>
    </table>
    </form>
    <tiles:insertDefinition name="postbody" />
    <tiles:insertDefinition name="footer" />
    sprin
    ~~~~


    ## Q#1:

    There are a couple possible approaches here.

    * Approach #1: If you have other attributes that you want to add to your UserDetails object, then you should provide your own alternate implementation of the UserDetails interface that includes those attributes along with corresponding getters and setters. This would require that you also provide your own alternate implementation of the UserDetailsService interface. This component would have to understand how to persist these additional attributes to the underlying datastore, or when reading from that datastore, would have to understand how to populate those additional attributes. You'd wire all of this up like so:
    * Approach #1: If you have other attributes that you want to add to your UserDetails object,
    then you should provide your own alternate implementation of the UserDetails interface that
    ncludes those attributes along with corresponding getters and setters. This would require
    that you also provide your own alternate implementation of the UserDetailsService interface.
    This component would have to understand how to persist these additional attributes to the
    underlying datastore, or when reading from that datastore, would have to understand how to
    populate those additional attributes. You'd wire all of this up like so:

    ~~~~
    <beans:bean id="userDetailsService" class="com.example.MyCustomeUserDetailsService">
    @@ -102,14 +126,35 @@ There are a couple possible approaches here.
    </beans:bean>
    ~~~~

    * Approache #2: Like me, you may find (especially over the span of several iterations) that you're better served to keep domain-specific user/account details separate from Spring Security specific user/account details. This may or may not be the case for you. But if you can find any wisdom in this approach, then you'd stick with the setup you have currently and add an additional User/Account domain object, corresponding repository/DAO, etc. If you want to retrieve the domain-specific user/account, you can do so as follows:
    * Approache #2: Like me, you may find (especially over the span of several iterations)
    that you're better served to keep domain-specific user/account details separate from
    Spring Security specific user/account details. This may or may not be the case for you.
    But if you can find any wisdom in this approach, then you'd stick with the setup you
    have currently and add an additional User/Account domain object, corresponding
    repository/DAO, etc. If you want to retrieve the domain-specific user/account, you
    can do so as follows:

    User user = userDao.getByUsername(SecurityContextHolder.getContext().getAuthentication().getName());

    ## Q#2:

    Spring Security automatically stores the UserDetails in the session (unless you've explicitly taken steps to override that behavior). So there's no need for you to do this yourself in each of your controller methods. The SecurityContextHolder object you've been dealing with is actually populated (by SS) with SecurityContext including the Authentication object, UserDetails, etc. at the beginning of every request. This context is cleared at the end of each request, but the data always remains in the session.

    It's worth noting, however, that it's not really a great practice to be dealing with HttpServletRequest, HttpSession objects, etc. in a Spring MVC controller if you can avoid it. Spring almost always offers cleaner, more idiomatic means of achieving things without the need for doing so. The advantage to that would be that controller method signatures and logic cease to be dependent on things that are difficult to mock in a unit test (e.g. the HttpSession) and instead of dependent on your own domain objects (or stubs/mocks of those domain objects). This drastically increases the testability of your controllers... and thus increases the liklihood that you actually WILL test your controllers. :)
    Spring Security automatically stores the UserDetails in the **session** (unless you've
    explicitly taken steps to override that behavior). So there's no need for you to do this
    yourself in each of your controller methods. The SecurityContextHolder object you've been
    dealing with is actually populated (by SS) with SecurityContext including the
    Authentication object, UserDetails, etc. at the beginning of every request. This context
    is cleared at the end of each request, but the data always remains in the session.

    It's worth noting, however, that it's not really a great practice to be dealing with
    HttpServletRequest, HttpSession objects, etc. in a Spring MVC controller if you can
    avoid it.

    Spring almost always offers cleaner, more idiomatic means of achieving things without
    the need for doing so. The advantage to that would be that controller method signatures
    and logic cease to be dependent on things that are difficult to mock in a unit test
    (e.g. the HttpSession) and instead of dependent on your own domain objects (or
    stubs/mocks of those domain objects). This drastically increases the testability of
    your controllers... and thus increases the liklihood that you actually WILL test your
    controllers. :)

    Hope this helps some.
  13. @esfand esfand revised this gist Oct 3, 2013. 1 changed file with 65 additions and 2 deletions.
    67 changes: 65 additions & 2 deletions customuserdetails.md
    Original file line number Diff line number Diff line change
    @@ -22,7 +22,68 @@ user's userDetails in a session upon login so that I don't need to also call
    at the beginning of every method?**


    Q#1: There are a couple possible approaches here.
    Security-applicationContext.xml:

    ~~~~
    <global-method-security secured-annotations="enabled"></global-method-security>
    <http auto-config='true' access-denied-page="/access-denied.html">
    <!-- NO RESTRICTIONS -->
    <intercept-url pattern="/login.html" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    <intercept-url pattern="/*.html" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    <!-- RESTRICTED PAGES -->
    <intercept-url pattern="/admin/*.html" access="ROLE_ADMIN" />
    <intercept-url pattern="/member/*.html" access="ROLE_ADMIN, ROLE_STAFF" />
    <form-login login-page="/login.html"
    login-processing-url="/loginProcess"
    authentication-failure-url="/login.html?login_error=1"
    default-target-url="/member/home.html" />
    <logout logout-success-url="/login.html"/>
    </http>
    <authentication-manager>
    <authentication-provider>
    <jdbc-user-service data-source-ref="dataSource"
    authorities-by-username-query=
    "SELECT U.username, UR.authority, U.userid FROM users U, userroles UR WHERE U.username=? AND U.roleid=UR.roleid LIMIT 1" />
    <password-encoder hash="md5"/>
    </authentication-provider>
    </authentication-manager>
    ~~~~

    login.jsp:

    ~~~~
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
    <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
    <tiles:insertDefinition name="header" />
    <tiles:insertDefinition name="menu" />
    <tiles:insertDefinition name="prebody" />
    <h1>Login</h1>
    <c:if test="${not empty param.login_error}">
    <font color="red"><c:out value="${SPRING_SECURITY_LAST_EXCEPTION.message}"/>.<br /><br /></font>
    </c:if>
    <form name="f" action="<c:url value='/loginProcess'/>" method="POST">
    <table>
    <tr><td>User:</td><td><input type='text' name='j_username' value='<c:if test="${not empty param.login_error}"><c:out value="${SPRING_SECURITY_LAST_USERNAME}"/></c:if>' /></td></tr>
    <tr><td>Password:</td><td><input type='password' name='j_password' /></td></tr>
    <tr><td>&nbsp;</td><td><input type="checkbox" name="_spring_security_remember_me" /> Remember Me</td></tr>
    <tr><td>&nbsp;</td><td><input name="submit" type="submit" value="Login" /></td></tr>
    </table>
    </form>
    ~~~~

    <tiles:insertDefinition name="postbody" />
    <tiles:insertDefinition name="footer" />
    sprin

    ## Q#1:

    There are a couple possible approaches here.

    * Approach #1: If you have other attributes that you want to add to your UserDetails object, then you should provide your own alternate implementation of the UserDetails interface that includes those attributes along with corresponding getters and setters. This would require that you also provide your own alternate implementation of the UserDetailsService interface. This component would have to understand how to persist these additional attributes to the underlying datastore, or when reading from that datastore, would have to understand how to populate those additional attributes. You'd wire all of this up like so:

    @@ -45,7 +106,9 @@ Q#1: There are a couple possible approaches here.

    User user = userDao.getByUsername(SecurityContextHolder.getContext().getAuthentication().getName());

    Q#2: Spring Security automatically stores the UserDetails in the session (unless you've explicitly taken steps to override that behavior). So there's no need for you to do this yourself in each of your controller methods. The SecurityContextHolder object you've been dealing with is actually populated (by SS) with SecurityContext including the Authentication object, UserDetails, etc. at the beginning of every request. This context is cleared at the end of each request, but the data always remains in the session.
    ## Q#2:

    Spring Security automatically stores the UserDetails in the session (unless you've explicitly taken steps to override that behavior). So there's no need for you to do this yourself in each of your controller methods. The SecurityContextHolder object you've been dealing with is actually populated (by SS) with SecurityContext including the Authentication object, UserDetails, etc. at the beginning of every request. This context is cleared at the end of each request, but the data always remains in the session.

    It's worth noting, however, that it's not really a great practice to be dealing with HttpServletRequest, HttpSession objects, etc. in a Spring MVC controller if you can avoid it. Spring almost always offers cleaner, more idiomatic means of achieving things without the need for doing so. The advantage to that would be that controller method signatures and logic cease to be dependent on things that are difficult to mock in a unit test (e.g. the HttpSession) and instead of dependent on your own domain objects (or stubs/mocks of those domain objects). This drastically increases the testability of your controllers... and thus increases the liklihood that you actually WILL test your controllers. :)

  14. @esfand esfand revised this gist Oct 3, 2013. 1 changed file with 6 additions and 4 deletions.
    10 changes: 6 additions & 4 deletions customuserdetails.md
    Original file line number Diff line number Diff line change
    @@ -10,22 +10,23 @@ a controller by using:
    There are a lot of other user details I would like stored when a user logs in
    (such as DOB, gender, etc.) and to be accessible via the controllers later on.

    * What do I need to do so that the userDetails object that is created contains
    my custom fields?
    * **What do I need to do so that the userDetails object that is created contains
    my custom fields?**

    I'm already calling `HttpSession session = request.getSession(true);` at the top
    of each of my methods in my controller.

    * Is it possible to store the logged in
    * **Is it possible to store the logged in
    user's userDetails in a session upon login so that I don't need to also call
    `Authentication auth = SecurityContextHolder.getContext().getAuthentication();`
    at the beginning of every method?
    at the beginning of every method?**


    Q#1: There are a couple possible approaches here.

    * Approach #1: If you have other attributes that you want to add to your UserDetails object, then you should provide your own alternate implementation of the UserDetails interface that includes those attributes along with corresponding getters and setters. This would require that you also provide your own alternate implementation of the UserDetailsService interface. This component would have to understand how to persist these additional attributes to the underlying datastore, or when reading from that datastore, would have to understand how to populate those additional attributes. You'd wire all of this up like so:

    ~~~~
    <beans:bean id="userDetailsService" class="com.example.MyCustomeUserDetailsService">
    <!-- ... -->
    </beans:bean>
    @@ -38,6 +39,7 @@ Q#1: There are a couple possible approaches here.
    class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
    <beans:property name="userDetailsService" ref="userDetailsService"/>
    </beans:bean>
    ~~~~

    * Approache #2: Like me, you may find (especially over the span of several iterations) that you're better served to keep domain-specific user/account details separate from Spring Security specific user/account details. This may or may not be the case for you. But if you can find any wisdom in this approach, then you'd stick with the setup you have currently and add an additional User/Account domain object, corresponding repository/DAO, etc. If you want to retrieve the domain-specific user/account, you can do so as follows:

  15. @esfand esfand revised this gist Oct 3, 2013. 1 changed file with 15 additions and 12 deletions.
    27 changes: 15 additions & 12 deletions customuserdetails.md
    Original file line number Diff line number Diff line change
    @@ -24,22 +24,25 @@ at the beginning of every method?

    Q#1: There are a couple possible approaches here.

    Approach #1: If you have other attributes that you want to add to your UserDetails object, then you should provide your own alternate implementation of the UserDetails interface that includes those attributes along with corresponding getters and setters. This would require that you also provide your own alternate implementation of the UserDetailsService interface. This component would have to understand how to persist these additional attributes to the underlying datastore, or when reading from that datastore, would have to understand how to populate those additional attributes. You'd wire all of this up like so:
    * Approach #1: If you have other attributes that you want to add to your UserDetails object, then you should provide your own alternate implementation of the UserDetails interface that includes those attributes along with corresponding getters and setters. This would require that you also provide your own alternate implementation of the UserDetailsService interface. This component would have to understand how to persist these additional attributes to the underlying datastore, or when reading from that datastore, would have to understand how to populate those additional attributes. You'd wire all of this up like so:

    <beans:bean id="userDetailsService" class="com.example.MyCustomeUserDetailsService">
    <!-- ... -->
    </beans:bean>
    <beans:bean id="userDetailsService" class="com.example.MyCustomeUserDetailsService">
    <!-- ... -->
    </beans:bean>

    <authentication-manager alias="authenticationManager">
    <authentication-provider ref="authenticationProvider"/>
    </authentication-manager>
    <authentication-manager alias="authenticationManager">
    <authentication-provider ref="authenticationProvider"/>
    </authentication-manager>

    <beans:bean id="authenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
    <beans:property name="userDetailsService" ref="userDetailsService"/>
    </beans:bean>
    Approache #2: Like me, you may find (especially over the span of several iterations) that you're better served to keep domain-specific user/account details separate from Spring Security specific user/account details. This may or may not be the case for you. But if you can find any wisdom in this approach, then you'd stick with the setup you have currently and add an additional User/Account domain object, corresponding repository/DAO, etc. If you want to retrieve the domain-specific user/account, you can do so as follows:
    <beans:bean id="authenticationProvider"
    class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
    <beans:property name="userDetailsService" ref="userDetailsService"/>
    </beans:bean>

    * Approache #2: Like me, you may find (especially over the span of several iterations) that you're better served to keep domain-specific user/account details separate from Spring Security specific user/account details. This may or may not be the case for you. But if you can find any wisdom in this approach, then you'd stick with the setup you have currently and add an additional User/Account domain object, corresponding repository/DAO, etc. If you want to retrieve the domain-specific user/account, you can do so as follows:

    User user = userDao.getByUsername(SecurityContextHolder.getContext().getAuthentication().getName());

    User user = userDao.getByUsername(SecurityContextHolder.getContext().getAuthentication().getName());
    Q#2: Spring Security automatically stores the UserDetails in the session (unless you've explicitly taken steps to override that behavior). So there's no need for you to do this yourself in each of your controller methods. The SecurityContextHolder object you've been dealing with is actually populated (by SS) with SecurityContext including the Authentication object, UserDetails, etc. at the beginning of every request. This context is cleared at the end of each request, but the data always remains in the session.

    It's worth noting, however, that it's not really a great practice to be dealing with HttpServletRequest, HttpSession objects, etc. in a Spring MVC controller if you can avoid it. Spring almost always offers cleaner, more idiomatic means of achieving things without the need for doing so. The advantage to that would be that controller method signatures and logic cease to be dependent on things that are difficult to mock in a unit test (e.g. the HttpSession) and instead of dependent on your own domain objects (or stubs/mocks of those domain objects). This drastically increases the testability of your controllers... and thus increases the liklihood that you actually WILL test your controllers. :)
  16. @esfand esfand revised this gist Oct 3, 2013. 1 changed file with 22 additions and 0 deletions.
    22 changes: 22 additions & 0 deletions customuserdetails.md
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,25 @@
    I'm pretty new to Java and Spring 3 (used primarily PHP the past 8 years).
    I've gotten spring security 3 to work with all the default userDetails and
    userDetailsService and I know I can access the logged in user's username in
    a controller by using:

    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    String username = auth.getName(); //get logged in username
    But there are two problems I can't figure out:

    There are a lot of other user details I would like stored when a user logs in
    (such as DOB, gender, etc.) and to be accessible via the controllers later on.

    * What do I need to do so that the userDetails object that is created contains
    my custom fields?

    I'm already calling `HttpSession session = request.getSession(true);` at the top
    of each of my methods in my controller.

    * Is it possible to store the logged in
    user's userDetails in a session upon login so that I don't need to also call
    `Authentication auth = SecurityContextHolder.getContext().getAuthentication();`
    at the beginning of every method?


    Q#1: There are a couple possible approaches here.
  17. @esfand esfand created this gist Oct 3, 2013.
    25 changes: 25 additions & 0 deletions customuserdetails.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,25 @@


    Q#1: There are a couple possible approaches here.

    Approach #1: If you have other attributes that you want to add to your UserDetails object, then you should provide your own alternate implementation of the UserDetails interface that includes those attributes along with corresponding getters and setters. This would require that you also provide your own alternate implementation of the UserDetailsService interface. This component would have to understand how to persist these additional attributes to the underlying datastore, or when reading from that datastore, would have to understand how to populate those additional attributes. You'd wire all of this up like so:

    <beans:bean id="userDetailsService" class="com.example.MyCustomeUserDetailsService">
    <!-- ... -->
    </beans:bean>

    <authentication-manager alias="authenticationManager">
    <authentication-provider ref="authenticationProvider"/>
    </authentication-manager>

    <beans:bean id="authenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
    <beans:property name="userDetailsService" ref="userDetailsService"/>
    </beans:bean>
    Approache #2: Like me, you may find (especially over the span of several iterations) that you're better served to keep domain-specific user/account details separate from Spring Security specific user/account details. This may or may not be the case for you. But if you can find any wisdom in this approach, then you'd stick with the setup you have currently and add an additional User/Account domain object, corresponding repository/DAO, etc. If you want to retrieve the domain-specific user/account, you can do so as follows:

    User user = userDao.getByUsername(SecurityContextHolder.getContext().getAuthentication().getName());
    Q#2: Spring Security automatically stores the UserDetails in the session (unless you've explicitly taken steps to override that behavior). So there's no need for you to do this yourself in each of your controller methods. The SecurityContextHolder object you've been dealing with is actually populated (by SS) with SecurityContext including the Authentication object, UserDetails, etc. at the beginning of every request. This context is cleared at the end of each request, but the data always remains in the session.

    It's worth noting, however, that it's not really a great practice to be dealing with HttpServletRequest, HttpSession objects, etc. in a Spring MVC controller if you can avoid it. Spring almost always offers cleaner, more idiomatic means of achieving things without the need for doing so. The advantage to that would be that controller method signatures and logic cease to be dependent on things that are difficult to mock in a unit test (e.g. the HttpSession) and instead of dependent on your own domain objects (or stubs/mocks of those domain objects). This drastically increases the testability of your controllers... and thus increases the liklihood that you actually WILL test your controllers. :)

    Hope this helps some.