没有servlet的Java客户端身份验证

时间:2018-02-14 12:03:52

标签: java authentication

我已经开发了一个独立的应用程序,现在我想执行身份验证

其中一种方法是使用servlet,但我希望我的应用程序是独立的应用程序,不需要与服务器通信。

所以我的登录代码是

    //loads the login screen
    @Override
public void start(Stage primaryStage) throws IOException {
    Parent root = FXMLLoader.load(getClass().getResource("login.fxml"));
    primaryStage.setTitle("Login screen");
    Scene loginscene = new Scene(root,700, 700);
   loginscene.setOnKeyPressed(new EventHandler<KeyEvent>() {
       @Override
       public void handle(KeyEvent event) {
           switch (event.getCode()){
               case ENTER:{
                   onLogin();
               }
           }
       }
   });
    primaryStage.setScene(loginscene);
    primaryStage.initStyle(StageStyle.UNDECORATED);
     primaryStage.getIcons().add(new Image("file:icon.png"));
     primaryStage.centerOnScreen();
    primaryStage.setResizable(false);
    primaryStage.show();
}

登录方法是

onLOgin(){

   //here am stuck on how to proceed

  }

有没有人知道我应该怎么做。 应用程序可以直接连接到mysql或mssql数据库,因此密码可以存储在那里,但我想以散列形式存储它,以便用户无法直接看到密码

我如何处理这种情况。对于java来说还是新手。

1 个答案:

答案 0 :(得分:1)

在开发身份验证时,我遵循了guide。 它描述了如何破解密码以及保护用户密码需要执行的操作。提供有关散列过程的一些好的技巧。 简而言之:

  • 只存储您的密码哈希(和盐,见下文)
  • 使用现有的散列函数 - 它们比发明自己的散列更好
  • hash with salt - salt是随机的,所以即使相同的密码也会有不同的哈希值
  • 必须为每次密码更改生成salt

所以在数据库中你需要2到3列

  • 登录名
  • 密码哈希
  • salt(如果没有组合成密码哈希)

身份验证将根据提供的密码(和存储的salt)创建哈希值,并将其与存储的哈希值(在指定的登录名下)进行比较。无效登录名或密码的错误消息应相同(用户名或密码无效),因此不容易找到用户名。

在幕后,我的身份验证方法如下所示:

public User authenticate(String login, String password) {
    final User user = UserService.getInstance().getUser(login);
    if(user != null) {
        //check password
        byte[] passwordHash = PasswordManipulator.instance.hash(password, user.getPasswordSalt());
        if(Arrays.equals(passwordHash, user.getPasswordHash())) {
            return user;
        }
        else {
            // invalid password, we return no user
            return null;
        }
    }
    return null;
}

返回null表示登录或密码无效。 UserService只是读取用户表并将其作为用户对象返回。

PasswordManipulator如下所示:

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;

import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;

public class PasswordManipulator {
private static final int SaltLength = 32;
private static final int IterationCount = 65536;
private static final int KeyLength = 256;
private final SecureRandom random = new SecureRandom();
SecretKeyFactory factory = null;

public static final PasswordManipulator instance = new PasswordManipulator();

private PasswordManipulator() {

}

public byte[] createSalt() {
    byte[] salt = new byte[SaltLength];
    random.nextBytes(salt);
    return salt;
}

public byte[] hash(String password, byte[] salt) {
    init();
    if(password == null || password.isEmpty()) {
        throw new IllegalArgumentException("Password is null or empty");
    }
    if(salt == null ) {
        throw new IllegalArgumentException("Salt is null!");
    }
    if(salt.length != SaltLength) {
        throw new IllegalArgumentException("Salt length is not valid. Expected length is " + SaltLength + ", but length is " + salt.length);
    }
    PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, IterationCount, KeyLength);
    try {
        byte[] hash = factory.generateSecret(spec).getEncoded();
        return hash;
    } catch (InvalidKeySpecException e) {
        throw new IllegalArgumentException("Failed to create password hash", e);
    }
}

private void init(){
    if(factory == null) {
        try {
            factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException("Cannot init " + this.getClass(), e);
        }
    }
}

}

您可能需要将一些数据库嵌入到您的应用程序中,或者在客户端上设置其他数据库方式。检查嵌入式数据库的this比较。要使用标准JDBC方式连接到数据库。

如果用户忘记密码,您会怎么做?标准方法是使用电子邮件进行密码恢复(并且用户登录等于电子邮件或电子邮件是必需的用户信息),但这需要在线连接。也许有一些用户必须正确回答的密码恢复备份问题。或者,如果您有某种形式的管理用户,管理用户可以重置标准用户的密码。

还有其他一种身份验证方式,例如使用Active directory,但您需要设置一些基础设施来连接它。

相关问题