当前位置: 首页 > 知识库问答 >
问题:

如果我们在实体类的getter和setter中添加逻辑,这是一个糟糕的设计吗

张昊穹
2023-03-14

JAVA 8

我有一门POJO课程:

class User {
    private String name;
    private String password;

    //... Getters / Setters ...
}

我将使用它作为实体类。

在密码的getter/setter中,我想添加解密/加密逻辑。

public String getPassword() {
    return EncryptionFactory.decryption(password);
}

public void setPassword(String password) {
    this.password = EncryptionFactory.encryption(password);
}

加密工厂(EncryptionFactory)是一个对字符串进行加密/解密的实用程序类。

根据一般的Java编码准则,如果我添加逻辑来更改密码,它是破坏设计还是糟糕的设计?

在使用它的时候,我从我的教授那里得到了糟糕的设计反馈。

共有1个答案

孙风畔
2023-03-14

通常setter伴随着getter(也称为访问器),它返回私有成员变量的值

由于getter是用来访问私有字段值的,因此它违反了最不令人惊讶的原则:可能会引发异常,EncrpytionFactory的impl可能会在某个时候失效,等等。。。当开发人员希望只访问一个值时。

你是否认为这个设计很糟糕取决于你的设计标准有多严格。确定的最佳方法是查看缺点:

  • 无法获取加密密码
  • 强制使用String作为纯文本密码来存储密码(因为setPassword会自动加密)
  • 在包含get/setPassword
  • 的类型中引入 EncrpytionFactory的依赖项

因此,在您的特定情况下,这是一个糟糕的设计。

尽管在某些情况下,一些开发人员可能会首选它。例如,如果您有一个Person#getAge():int,但使用了一个Date属性来管理此人的年龄:

class Person {
    private Date dateOfBirth;

    public int getAge() {
        Date now = ...; //grab date/time right now
        int age = ...; //calculate age using dateOfBirth and now

        return age;
    }

有些人会争辩说,计算应该是解耦的,或者应该命名为calculateAge。

来自wiki文章:

相反,访问器允许从内部变量合成有用的数据表示,同时保持它们的结构封装并隐藏在外部模块之外。货币getAmount访问器可以从数字变量构建字符串,其小数位数由隐藏的货币参数定义。

你真的想解密密码吗,比如,有什么理由吗?假设你想维护安全,有更安全的方法来维护密码。

无论何时,只要将输入的密码与存储的密码进行比较,只需加密输入的密码并将结果与存储的密码进行比较即可。

如果有人想“恢复”他们的密码,以明文形式向用户发送他们的密码将存在安全风险。这就是为什么大型企业要求您在忘记密码时重置密码的原因。

你真的需要在每次有人调用getPassword()时解密吗?如果有人想要encrpyted值呢?

您应该将解密与访问分开。查看您已经拥有的加密工厂:

User user = ...;
String encryptedPassword = user.getPassword();
String decryptedPassword = EncryptionFactory.decryption(encryptedPassword);

应该只有很少几次您的密码被解密(有些人可能会认为它不应该存在于内存中解密)。关键是,它应该是完全可选的。

密码应设置为已加密:

String encryptedPassword = EncryptionFactory.encrpytion(...);

User user = ...;
user.setPassword(encryptedPassword);

它应该以加密形式访问。您永远不应该强制这样的安全风险(解密密码),使其可选。

最后,如果必须公开解密的getPassword备选方案,则应将其重命名为decryptPassword():

public String decryptPassword() {
    return EncrpytionFactory.decryption(getPassword());
}

尽管这在用户(或您使用的任何类型)和加密工厂(EncryptionFactory)之间引入了不必要的耦合。

您应该更深入地了解安全方面。您不应该将解密后的密码保存为字符串,如果只有用户知道密码,这是最安全的。

 类似资料:
  • 我有一个web应用程序,它在后台做一些可靠的文档处理工作。用户上传文档进行处理后,最多需要20秒才能完成处理。现在,我尝试使用每秒更新一次的进度条来吸引用户。 如果一个Web应用程序需要20秒来做一些严肃的后端处理,它是一个糟糕的应用程序吗? 您是否遇到过处理时间超过10-15秒的Web应用程序?互联网上有没有流行的网站也这样做? 将这种耗时的应用程序重新设计为批处理驱动的应用程序有意义吗?在处理

  • 我有一个类名计算器(getter-setter类型类)。我使用volley jar从json收集所有值。现在我想在arraylist的零索引处添加新值。但我不能这样做。这是代码。 内部onCreate方法 之后,我调用函数从json获取值。 现在添加到微调器。但在零指数时,我得到了货币名称。我希望在零指数处添加“选择货币”。我使用下面的代码来获得我想要的 这给了我错误- 类型列表中的add(int

  • 一进去,面试官迟到,等了近十分钟,面试官到了,开始面试 先狂问我的毕设,具体到其中的算法实现。由于算法不是自己写的,具体细节并不了解,就只能说不会,然后就被质疑是不是自己做的,在毕设中担任了什么工作,怎么具体细节都不清楚,我只能说是使用了别人做的算法包,具体实现细节不是特别清楚 之后开始正式的java坐牢环节 一上来直接问我用的jdk版本,我说了jdk8,然后居然问我为什么用jdk8。我直接一脸问

  • 我的下一个想法是将时态数据作为分区密钥的一部分。这似乎是有意义的,因为我们每天都在批量导入大量的时间戳数据。而且,99%的针对该数据库的查询都包含日期范围。我提出了一个派生的抽象值,在上面的文档中标记为。此值将帐户id与时间因子(每个电话的年和月)组合在一起。使用该方案,每个租户每年将获得12个分区,而不是整个帐户的单个分区。每个租户的容量仍然不同,所以我们仍然会有一些大的分区和一些小的分区。但是

  • 当我尝试用Jenkins构建一个maven工件时,build输出如下: 我已经在1.0版上成功地构建了一堆。我正在使用CentOS和Nexus3操作系统。

  • 若要添加一个新的实体,点击工具栏的 “实体”按钮,并点击画布的任意位置。你可以从浏览器的模型选项卡添加一个现有的实体,简单地从模型选项卡拖放实体到画布。 如果图表符号设置为默认, 图标代表属性为一个主键。而 图标则代表属性为一个索引。 【注意】如果你按住 Control 键并点按属性,你可以选择添加、插入、删除、重命名属性及设置属性为主键。 在画布中实体对象的弹出式菜单选项包括: 选项 描述 设计