2013-07-24 2 views
0

비밀번호 해시에 문제가 있습니다.해시 차이

다음 코드는 jsf-Page를 통해 서버에 로그인하려고 시도하지만 Method 로그인이 호출되면 기본 데이터베이스에서 암호 해시가 변경됩니다. 버전 9.2에서 postgresql 데이터베이스를 사용하고 있습니다. 이유를 파악할 수 없습니다. 누구든지 도울 수 있니?

은 JSF 페이지 :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"` "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:h="http://java.sun.com/jsf/html" 
    xmlns:f="http://java.sun.com/jsf/core" 
    xmlns:ui="http://java.sun.com/jsf/facelets" 
    xmlns:c="http://java.sun.com/jsp/jstl/core"> 

<h:head> 
    <meta http-equiv="Content-Type" content="text/html;charset=UTF8" /> 
</h:head> 
<body> 
    <h1>Login</h1> 
    <div id="container"> 
     <h:form id="create"> 
      <h:commandButton id="create" value="create" 
       action="#{login.create()}"> 
      </h:commandButton> 
     </h:form> 
     <h:form id="loginForm"> 
      <h:panelGrid columns="2"> 
       <h:outputLabel>Username:</h:outputLabel> 
       <h:inputText value="#{username}" /> 
      </h:panelGrid> 
      <h:panelGrid columns="2"> 
       <h:outputLabel>Password:</h:outputLabel> 
       <h:inputText value="#{password}" /> 
      </h:panelGrid> 
      <h:commandButton id="login" value="Login" 
       action="#{loginController.login(username, password)}"> 
      </h:commandButton> 
     </h:form> 
     <h:form id="response"> 
      <h:panelGrid columns="2"> 
       <h:outputLabel>Response:</h:outputLabel> 
       <h:outputLabel value="#{login.username}" /> 
      </h:panelGrid> 
     </h:form> 

    </div> 
</body> 
</html> 

인 LoginController :

import java.io.Serializable; 
import java.util.logging.Level; 
import java.util.logging.Logger; 

import javax.annotation.ManagedBean; 
import javax.ejb.EJB; 
import javax.enterprise.context.SessionScoped; 
import javax.inject.Named; 

import de.lps.entities.User; 
import de.lps.server.interfaces.ILPSServerUser; 
import de.lps.server.server.LPSServer; 

@Named("loginController") 
@SessionScoped 
public class LoginController implements Serializable { 
    /** 
    * 
    */ 
    private static final long serialVersionUID = 1L; 

    @EJB(beanInterface=ILPSServerUser.class) 
    private ILPSServerUser server; 

    private Logger logger; 

    String username; 

    public void login(String username, String password) { 
     this.logger = Logger.getLogger("LoginController"); 

     this.logger.log(Level.INFO, server.toString()); 

     if (username != "" && password != "") { 
      User user = server.login(username, password); 
      if (user == null) { 
       this.logger.log(Level.INFO, "user == null"); 
       this.username = "User N.A"; 
      } else { 
       this.logger.log(Level.INFO, "got user"); 
       this.username = user.getUserName(); 
      } 

     } else { 
      this.logger.log(Level.INFO, "No credentials were given"); 
      this.username = "No credentials were given"; 
     } 

    } 

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

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

} 

호출 된 EJB :

package de.lps.server.server; 

import java.util.logging.Level; 
import java.util.logging.Logger; 

import javax.ejb.Stateful; 
import javax.persistence.EntityManager; 
import javax.persistence.PersistenceContext; 

import de.lps.entities.User; 
import de.lps.server.interfaces.ILPSServerUser; 
import de.lps.utils.security.PasswordHash; 

/** 
* Session Bean implementation class LPSServer 
*/ 
@Stateful 
public class LPSServer implements ILPSServerUser { 
    private User loggedUser; 
    @PersistenceContext 
    EntityManager em; 

    Logger logger = Logger.getLogger(LPSServer.class.getPackage().getName()); 

    /** 
    * Default constructor. 
    */ 
    public LPSServer() { 
     // TODO Auto-generated constructor stub 
    } 

    @Override 
    public User login(String username, String password) { 
     if (loggedUser == null) { 
      User user = em.find(User.class, username); 

      if (user != null) { 
       if (PasswordHash.comparePasswordWithHash(password, 
         user.getPassword())) { 
        loggedUser = user; 
        logger.log(Level.INFO, "Loggedin successfull | username=" 
          + username); 
        return loggedUser; 
       } 

       logger.log(Level.WARNING, "GIVEN_PASSWORD_HASH[ " 
         + PasswordHash.hash(password) 
         + " ] SAVED_PASSWORD_HASH[ " + user.getPassword() 
         + " ]"); 
       logger.log(
         Level.INFO, 
         "Not logged in due wrong password| username=" 
           + user.getUserName()); 

      } else { 
       logger.log(Level.INFO, 
         "Not logged in due wrong username| username=" 
           + username); 
      } 

     } 
     else{ 
      return loggedUser; 
     } 
     return null; 
    } 

    @Override 
    public void logout() { 
     // TODO Auto-generated method stub 
     logger.log(Level.INFO, loggedUser.getUserName() + " logged out"); 
     this.loggedUser = null; 

    } 

    @Override 
    public void createUser(String username, String password) { 
     // TODO Auto-generated method stub 
     User user = new User(); 
     user.setUserName(username); 
     user.setPassword(password); 
     em.persist(user); 
     logger.log(Level.INFO, "User created"); 

    } 

} 

암호 해싱 방법 :

package de.lps.utils.security; 

import java.io.UnsupportedEncodingException; 
import java.security.MessageDigest; 
import java.security.NoSuchAlgorithmException; 

import javax.xml.bind.DatatypeConverter; 

public class PasswordHash { 
    /** 
    * 
    * @param password 
    * @return returns the md5-hash of the password if the password == null returns null 
    */ 
    public static String hash(String password){ 
     if(null == password){ 
      return null; 
     } 
     MessageDigest sha256; 
     try { 
      sha256 = MessageDigest.getInstance("SHA-256"); 
      byte[] passBytes = password.getBytes("UTF-8"); 
      byte[] passHash = sha256.digest(passBytes); 
      return DatatypeConverter.printHexBinary(passHash); 
     } catch (NoSuchAlgorithmException e) { 
      e.printStackTrace(); 
      return null; 
     } catch (UnsupportedEncodingException e) { 
      e.printStackTrace(); 
      return null; 
     }   

    } 

    /** 
    * Compares a specified password with a specified hash 
    * @param password 
    * @param hash 
    * @return return true when hash and password are equals 
    */ 
    public static boolean comparePasswordWithHash(String password, String hash){ 
     if(hash(password).equals(hash)){ 
      return true; 
     } 
     return false; 
    } 
} 
,691,363을 (210)

그리고 기업 사용자 : 당신의 도움에 대한

package de.lps.entities; 

import java.io.Serializable; 
import java.lang.String; 

import javax.persistence.*; 

import de.lps.utils.security.PasswordHash; 

/** 
* Entity implementation class for Entity: User 
* 
*/ 
@Entity 
@Table(name = "lps_user") 
public class User implements Serializable { 

    private String userName; 
    private String password; 

    private static final long serialVersionUID = 1L; 

    public User() { 
     super(); 
    } 

    @Id 
    @Column(name = "username") 
    public String getUserName() { 
     return this.userName; 
    } 

    public void setUserName(String userName) { 
     this.userName = userName; 
    } 

    @Column(name = "password", length=1000) 
    public String getPassword() { 
     return this.password; 
    } 

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

} 

감사 불쌍한 내 영어 실력

+0

안녕하세요. 우선, StackOverflow에 오신 것을 환영합니다! 몇 가지 질문이 있습니다. 작동 시키려면 어떤 단계를 밟았습니까? 어떤 오류 메시지가 나타 납니까? –

+0

그게 문제 였어. 오류 메시지가 없었어. 내 로그 파일에는 지정된 해시 isnt가 저장된 것과 동일하다고 표시됩니다. 그러나 Sotirios는 나에게 정확한 힌트를 줬다 :) – ZeusNet

+0

좋다. 그것은 가장 좌절하는 오류입니다. 다행히 해결책을 찾을 수있었습니다. –

답변

3

데이터베이스에서 User 인스턴스를로드하려고 할 때, 당신의 EntityManager이를 사용하기 때문에이 문제가 발생 죄송합니다 User#setPassword(String) setter는 테이블에서 가져 오는 password의 값을 설정합니다. 이렇게하면 암호 해시가 원래 해시는 아니지만 해시의 해시가되도록 다시 계산됩니다.

비밀번호를 설정 메소드 외부에 해시해야합니다.

+0

도움 주셔서 감사합니다. 그것은 작동합니다. – ZeusNet

+0

안녕하세요 @SotiriosDelimanolis,이 솔루션에 대한 추가 질문이 있습니다. 나는'EntityManager'를 호출 할 때 왜 데이터베이스에서 암호가 변경되었는지 이해하지 못합니다. 왜냐하면 이것은'EntityManager' 클래스의'persit' 메소드를 호출 할 때만 발생하기 때문입니다. – ZeusNet

+0

@Holger'EntityManager '는 데이터베이스의 엔터티를 쿼리하는데도 사용됩니다. 그렇게되면 리플렉션을 사용하여 엔티티를 인스턴스화하고 세터를 찾습니다. 그것들을 사용하여 다양한 인스턴스 필드를 설정합니다. 'password'는 그들 중 하나입니다. –