0

我在散列密码时遇到问题。

以下代码尝试通过 jsf 页面登录服务器,但是当调用方法登录时,底层数据库上的密码哈希值会发生变化。我在 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>

登录控制器:

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;
    }
}   

和实体用户:

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);        
    }

}

感谢您的帮助,并为我糟糕的英语能力感到抱歉

4

1 回答 1

3

发生这种情况是因为当您尝试User从数据库加载实例时,您EntityManager将使用User#setPassword(String)setter 设置password它从表中获取的值。这将重新计算密码哈希,因此您不会使用原始哈希,而是哈希的哈希。

您应该在 setter 方法之外对密码进行哈希处理。

于 2013-07-24T21:11:25.187 回答