【问题标题】:Most desirable way to save password in a class - Java在类中保存密码的最理想方式 - Java
【发布时间】:2012-12-19 15:22:06
【问题描述】:

我有两个类“User Profile”和“FingerprintProfile”,它们扩展了一个抽象类“Profile”。

简介:

/**
 * Template for User profiles or Fingerprint profiles
 */
public abstract class Profile {

    /**
     * Profile Name
     */
    private String name;

    /**
     * Profile id
     */
    private int id;

    /**
     * Set the name of this profile
     * @param name
     */
    public void setProfileName(String name) {
        this.name = name;
    }

    /**
     * Set the id of this profile
     * @param name
     */
    public void setIdNumber(int id) {
        this.id = id;
    }

    /**
     * Get the name of this profile
     */
    public String getProfileName() {

        return name;

    }

    /**
     * Get the id of this profile
     */
    public int getIdNumber() {
        return id;
    }

}

我的下一堂课是 UserProfile

public class UserProfile extends Profile {

    /**
     * Users password
     */
    private char[] password;

    /**
     * Set User password
     * @param password
     */
    public void setPassword(char[] password){

        this.password = password;

    }

    /**
     * Get User password
     */
    public char[] getPassword(){

        return password;

    }

}

光看这个类好像很狡猾,能这样找回密码似乎完全错误(即使get方法是private)。

在制作我的 FingerPrintProfile 类以及拥有一个“FingerprintData”对象时,我似乎将面临同样的问题,该对象本身也需要安全。

有没有人知道一种安全的方法,或者最好是人们用来解决这种情况的一种模式?

谢谢!

奖金问题

我创建了抽象类来为两种类型的配置文件提供模板,指纹数据和文本密码之间似乎存在共同点。但是,不可能创建一个可能是 char 数组或 FingerprintData 对象的抽象字段“密码”。有任何想法吗??

【问题讨论】:

  • 密码加密了吗?
  • 不是密码没有加密,你看的是我现在的开发阶段。

标签: java design-patterns passwords abstract-class password-protection


【解决方案1】:

使用密码时,您可能应该使用某种形式的加密,这样密码就不会以纯文本形式存储。您可以阅读here 的工作原理。

Here 是一个指向 Bcrypt 的 Java 实现的链接,它至少可以帮助您入门。

【讨论】:

    【解决方案2】:

    改用“对象思维”。您当前的设计根本不是 OOP。您应该公开个人资料的行为,而不是设置和获取密码。例如:

    interface Profile {
      void rename(String name);
      String identity();
      boolean authenticate(char[] password)
    }
    

    Getter/setter 是 OOP 中的一种反模式。

    【讨论】:

    • 那么具体类中的名称/密码字段是不是应该填写?
    • 我也可以为每个类(即指纹与用户)设置不同的身份验证方法吗?
    • authenticate() 如何使用提供的密码来验证(或拒绝)用户取决于您的实现。关键是你的类不应该暴露密码(通过getter),而应该封装它并暴露行为。
    • 这是我的首选方式,因为它允许您在不更改 API 的情况下实现加密密码(而不是明文密码)。
    • 嗯,getter/setter 确实是一种反模式,但我也认为 OO 应该模拟现实世界,而在现实世界中,通常我会将 Credentials 交给某种 Authenticator他们查看印有我的 UserProfile 的凭证,然后说,是的,这看起来是合法的。不知道其他国家是不是这样。 ;)
    【解决方案3】:

    有没有人知道一种安全的方法,或者最好是人们用来解决这种情况的一种模式?

    你需要问自己“安全防范什么?”。

    当然,如果某些不受信任的代码在与此类相同的 JVM 中执行,它可能会获取密码。但是为什么你会允许这种情况发生呢?

    • 您无法保护内存数据免受在同一 JVM 中以完全权限运行的不受信任代码的影响。

    • 如果您小心,您可以保护数据免受在安全沙箱中运行的不受信任的代码的影响;例如通过创建自定义 Permission 并使用 SecurityManager 检查(例如)getPassword 方法的调用者是否具有所需的权限。 (而且你还需要做一些其他的事情......)


    话虽如此,处理密码的“最佳实践”方法是使用(真正的)安全散列算法创建和存储种子散列。你可以在这里做同样的事情。问题是,如果您确实需要明确的密码,那将无法正常工作……因为散列的整个想法是使恢复密码变得不可行。但另一方面,如果密码是明确的,坏人可能会抓住它。

    加密存储密码对于 JVM 中不受信任的代码是不安全的。给定时间、精力和不受信任的人与坏人之间的隐蔽信息通道,应该可以恢复使用的密钥和算法,从而解密数据。坏人可能会通过核心转储或读取 JVM 进程的页面文件来获取信息。

    最重要的是,如果您的平台安全性遭到破坏(JVM 或操作系统),您无法保证明文或加密的密码将保持安全。

    【讨论】:

    • 感谢您的回复,这就是我所说的“似乎”错误的意思。对象字段可以以纯文本形式保存密码似乎并不正确。如果操作系统不存储密码,我的应用程序为什么要这样做?
    猜你喜欢
    • 2021-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-29
    • 1970-01-01
    • 1970-01-01
    • 2018-09-20
    • 2021-12-17
    相关资源
    最近更新 更多