【问题标题】:Working with byte[] properties使用 byte[] 属性
【发布时间】:2016-06-19 05:42:22
【问题描述】:

我正在编写一个 JavaFX 程序,它应该有用户管理和数据库后端。我的数据模型类都使用 JavaFX 风格的属性(为了更容易的 UI 集成,请参阅例如 this )。

但现在我遇到了一个技术问题,我的 User 类需要有 byte[] 字段 - 即用于 password hashsalt 的字段。

由于MessageDigest 和类似的Java 服务需要byte[],使用ObjectProperty<Byte[]> 的明显解决方案变得很麻烦,因为每次使用这些字段我都必须创建一个新的byte[] 并复制这些值。 例如:

SimpleObjectProperty<Byte[]> toHash = new SimpleObjectProperty<>();
MessageDigest md;
// initialize message digest and Byte[] property here...

// Does not compile - can't convert Byte[] to byte[]
// md.update(toHash.get());

// What does work: 
byte[] bytes = new byte[toHash.get().length];
for (int i=0; i<bytes.length; i++) 
    bytes[i] = toHash.get()[i];

md.update(bytes);

所以我的问题是 - 是否有一个简单的解决方案可以让我拥有 JavaFX 风格的属性,我可以使用原始数组获取和设置这些属性?
实施像PrimitiveByteArrayProperty 这样的选择是一个合理的选择,甚至是一个可行的选择吗?这样的解决方案是否已经存在?

编辑:我显然忽略了使用 ObjectProperty&lt;byte[]&gt; 的简单解决方案,因为我认为 Java 不允许原始数组的泛型。

【问题讨论】:

  • 为什么需要密码哈希和盐的属性?这应该在数据库或 LDAP 层的深处确定,而不是应用程序的可配置属性。
  • 我不熟悉JavaFX,但我不太明白使用字节数组有什么麻烦,为什么需要创建一个新的字节[]并复制值。我也不明白为什么你会使用 ObjectProperty 而不是 ObjectProperty。您能否详细说明,并提供一个繁琐代码的示例?
  • @JBNizet - 我假设 Java 对扩展到数组的类型参数中的原语的限制。看来我错了,在这种情况下问题确实无效。
  • @EJP - 它是客户端需要自定义用户授权处理的系统的一部分。虽然从技术上讲,这些属性从来都不是 UI 的一部分,但我仍然必须按照给定的规范自己实现它们。鉴于所有其余的处理都是使用 JFX 属性完成的,因此不要打破这个“约定”是很有说服力的。

标签: java javafx properties


【解决方案1】:

这样做的正确方法是:

/**
 * The password hash.
 */
private final ObjectProperty<byte[]> toHash = new SimpleObjectProperty<>(this, "toHash");
/**
 * Setter for toHash property value.
 * @param value of the password hash.
 */
public void setToHash(byte[] value){
    toHash.set(value);
}
/**
 * Getter for toHash property value.
 * @return value of the password hash.
 */
public byte[] getToHash(){
    return toHash.get();
}
/**
 * Accessor to the javaFX property toHash.
 * @return toHash javaFX property.
 */
public ObjectPropery<byte[]> toHashProperty(){
    return toHash;
}

javaFX 约定不返回属性特化(即:不会返回 SimpleObjectProperty),您应该返回 ObjectProperty、StringProperty、BooleanProperty... 另一方面, toHash 听起来像是一个计算哈希的函数名,而不是属性本身。一个更好的名字可能是passwordHash。或者,如果您在另一个属性中保存密码纯文本(出于安全原因显然不应该这样做),那么正确的 javaFX 方法应该是:

//The password hash property.
private final ReadOnlyObjectWrapper<byte[]> passwordHash =
new ReadOnlyObjectWrapper<>(this, "passwordHash");

//The password plain text property.
private final StringProperty passwordPlain =
new SimpleStringProperty(this, "passwordPlain");

public byte[] getPasswordHash(){
    return passwordHash.get();
}

public ReadOnlyObjectProperty<byte[]> passwordHashProperty(){
    return passwordHash.getReadOnlyProperty();
}

public MyClass(){
    //Bind your read only property to automatically reflect the plain password changes.
    passwordHash.bind(Bindings.createObjectBinding(this::computeHash, passwordPlain));
}

//Invoked from lambda method reference in object binding.
private byte[] computeHash(){
    //Here do your stuff to parse the password plain to byte[]
    return byteArray;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多