title: Spring Security - Random salt + Hash + Custom UserDetailsService
body: <p>Last question on this from me hopefully. So far I've implemented my own custom UserDetails and UserDetailsService classes so that I can pass the random salt that was used at the time of password creation. Hash of password is SHA512. However upon trying to login I always get user/pw combination incorrect and I can't seem to figure out why.</p>
  
  <p>I store the hash and salt in the db as blobs, any ideas on where the issue lies?</p>
  
  <pre><code>Security-applicationContext.xml
  
  &lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;beans:beans
    xmlns:sec="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans"
    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-3.0.xsd
             http://www.springframework.org/schema/security
             http://www.springframework.org/schema/security/spring-security-3.0.xsd"&gt;
  
      &lt;sec:http auto-config='true' access-denied-page="/access-denied.html"&gt;
          &lt;!-- NO RESTRICTIONS --&gt;        
          &lt;sec:intercept-url pattern="/login.html" access="IS_AUTHENTICATED_ANONYMOUSLY" /&gt;
          &lt;sec:intercept-url pattern="/*.html" access="IS_AUTHENTICATED_ANONYMOUSLY"  /&gt; 
          &lt;!-- RESTRICTED PAGES --&gt;
          &lt;sec:intercept-url pattern="/admin/*.html" access="ROLE_ADMIN" /&gt;
          &lt;sec:intercept-url pattern="/athlete/*.html" access="ROLE_ADMIN, ROLE_STAFF" /&gt;
  
          &lt;sec:form-login login-page="/login.html"
                      login-processing-url="/loginProcess"
                      authentication-failure-url="/login.html?login_error=1"
                      default-target-url="/member" /&gt;
          &lt;sec:logout logout-success-url="/login.html"/&gt;
      &lt;/sec:http&gt;
  
      &lt;beans:bean id="customUserDetailsService" class="PATH.TO.CustomUserDetailsService"/&gt;
      &lt;beans:bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder"&gt;
          &lt;beans:constructor-arg value="512"/&gt;
      &lt;/beans:bean&gt;
  
      &lt;sec:authentication-manager&gt;
          &lt;sec:authentication-provider user-service-ref="customUserDetailsService"&gt;
              &lt;sec:password-encoder ref="passwordEncoder"&gt; 
                  &lt;sec:salt-source user-property="salt"/&gt; 
              &lt;/sec:password-encoder&gt;
          &lt;/sec:authentication-provider&gt;
      &lt;/sec:authentication-manager&gt;
  &lt;/beans:beans&gt;
  </code></pre>
  
  <p>CustomUserDetails.java</p>
  
  <pre><code>public class CustomUserDetails implements UserDetails {
  
      private int userID;
      private String username;
      private String password;
      private Collection&lt;GrantedAuthority&gt; authorities;
      private boolean accountNonExpired;
      private boolean accountNonLocked;
      private boolean credentialsNonExpired;
      private boolean enabled;
      private String salt;
  
      public CustomUserDetails() {
      }
  
      public CustomUserDetails(int userID, Collection&lt;GrantedAuthority&gt; authorities, String username, String password, boolean accountNonExpired, boolean accountNonLocked, boolean credentialsNonExpired, boolean enabled, String salt) {
          this.userID = userID;
          this.authorities = authorities;
          this.username = username;
          this.password = password;
          this.accountNonExpired = accountNonExpired;
          this.accountNonLocked = accountNonLocked;
          this.credentialsNonExpired = credentialsNonExpired;
          this.enabled = enabled;
          this.salt = salt;
      }
  
      @Override
      public Collection&lt;GrantedAuthority&gt; getAuthorities() {
          return authorities;
      }
  
      public int getUserID() {
          return userID;
      }
  
      public void setUserID(int userID) {
          this.userID = userID;
      }
  
      @Override
      public String getPassword() {
          return password;
      }
  
      @Override
      public String getUsername() {
          return username;
      }
  
      @Override
      public boolean isAccountNonExpired() {
          return accountNonExpired;
      }
  
      @Override
      public boolean isAccountNonLocked() {
          return accountNonLocked;
      }
  
      @Override
      public boolean isCredentialsNonExpired() {
          return credentialsNonExpired;
      }
  
      @Override
      public boolean isEnabled() {
          return enabled;
      }
  
      public String getSalt() {
          return salt;
      }
  
      public void setAccountNonExpired(boolean accountNonExpired) {
          this.accountNonExpired = accountNonExpired;
      }
  
      public void setAccountNonLocked(boolean accountNonLocked) {
          this.accountNonLocked = accountNonLocked;
      }
  
      public void setAuthorities(Collection&lt;GrantedAuthority&gt; authorities) {
          this.authorities = authorities;
      }
  
      public void setCredentialsNonExpired(boolean credentialsNonExpired) {
          this.credentialsNonExpired = credentialsNonExpired;
      }
  
      public void setEnabled(boolean enabled) {
          this.enabled = enabled;
      }
  
      public void setPassword(String password) {
          this.password = password;
      }
  
      public void setUsername(String username) {
          this.username = username;
      }
  
      public void setSalt(String salt) {
          this.salt = salt;
      }
  }
  </code></pre>
  
  <p>CustomUserDetailsService.java</p>
  
  <pre><code>public class CustomUserDetailsService implements UserDetailsService {
  
      private User_dao userDao;
  
      @Autowired
      public void setUserDao(User_dao userDao) {
          this.userDao = userDao;
      }
  
      @Override
      public CustomUserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
          MyUser myUser = new MyUser();
          myUser.setUsername(username);
          try {
              userDao.getUserByUsername(myUser);
          } catch (Throwable e) {
          }
          if (myUser == null) {
              throw new UsernameNotFoundException("Username not found", username);
          } else {
              List&lt;GrantedAuthority&gt; authList = new ArrayList&lt;GrantedAuthority&gt;();
              authList.add(new GrantedAuthorityImpl(myUser.getUserRole().getAuthority()));
  
              int userID = myUser.getUserID();
              boolean accountNonExpired = true;
              boolean accountNonLocked = myUser.isNonLocked();
              boolean credentialsNonExpired = true;
              boolean enabled = myUser.isEnabled();
              String password = "";
              String salt = "";
  
              password = new String(myUser.getHash);
              salt = new String(myUser.getSalt());
              CustomUserDetails user = new CustomUserDetails(userID, authList, username, password, accountNonExpired, accountNonLocked, credentialsNonExpired, enabled, salt);
              return user;
          }
      }
  }
  </code></pre>
  
  <p>Password Creation</p>
  
  <pre><code>public byte[] generateSalt() throws NoSuchAlgorithmException {
      SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
      byte[] salt = new byte[20];
      random.nextBytes(salt);
      return salt;
  }
  
  public byte[] generateHash(byte[] salt, String pass) throws NoSuchAlgorithmException {
      MessageDigest digest = MessageDigest.getInstance("SHA-512");
      digest.update(salt);
      byte[] hash = digest.digest(pass.getBytes());
      return hash;
  }
  </code></pre>
  
  <p>Call in method:</p>
  
  <pre><code>byte[] salt = generateSalt();
  byte[] hash = generateHash(salt, password);
  Which I then store in the db.
  </code></pre>