【问题标题】:Choosing what pojo to use based on the user role on an edit request根据编辑请求中的用户角色选择要使用的 pojo
【发布时间】:2018-10-11 03:45:13
【问题描述】:

所以我想知道根据用户角色处理编辑请求的最佳方式是什么。

假设我有以下 PostMapping:

@PostMapping(value = "/edit")
public ResponseEntity<String> editIoc(@RequestBody GeneralPojoAllFields editRequest) 

GeneralPojoAllFields 如下所示:

public class GeneralPojoAllFields {    
    private String firstName;
    private String lastName;
    private String onlyAdminCanEditField;
}

这是管理员可以使用的 pojo,最终将映射到实体类中以保存到数据库中。但是,如果我们有一个想要编辑它的普通用户,并且假设他们在 UI 中不受限制,那么这种设计会起作用吗?我目前在想的是我会有一个像这样的用户 pojo:

public class UserPojo {    
    private String firstName;
    private String lastName;
}

请求映射后,我们检查用户是普通用户还是管理员。如果它是普通用户,我们只需将 GeneralPojoAllFields 映射到 UserPojo,它不会映射到 onlyAdminCanEditField 并从那里继续。

有没有更好的方法来做到这一点?

【问题讨论】:

  • 请将其中一个答案标记为绿色箭头对您有帮助的答案。否则,此帖子将保持打开状态。

标签: java spring roles


【解决方案1】:

嗯,这取决于您认为更好的方法是什么。它还取决于您的数据源。但由于这里没有这方面的信息,我建议更好的方法是通过继承。

使UserPojo 成为超类,GeneralPojoAllFields 扩展该类。

UserPojo.java:

public class UserPojo {
    private String firstName;
    private String lastName;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public UserPojo() {}

    public UserPojo(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

GeneralPojoAllFields.java:

public class GeneralPojoAllFields extends UserPojo {
    private String onlyAdminCanEditField;

    public String getOnlyAdminCanEditField() {
        return onlyAdminCanEditField;
    }

    public void setOnlyAdminCanEditField(String onlyAdminCanEditField) {
        this.onlyAdminCanEditField = onlyAdminCanEditField;
    }

    public GeneralPojoAllFields() {}

    public GeneralPojoAllFields(String firstName, String lastName, String onlyAdminCanEditField) {
        super(firstName, lastName);
        this.onlyAdminCanEditField = onlyAdminCanEditField;
    }
}

App.java:

public class App {
    public static void main(String[] args) {
        UserPojo up1 = new UserPojo();
        up1.setFirstName("MyFirstName");
        up1.setLastName("MyLastName");

        GeneralPojoAllFields gpaf1 = new GeneralPojoAllFields();
        gpaf1.setFirstName("MyFirstName");
        gpaf1.setLastName("MyLastName");
        gpaf1.setOnlyAdminCanEditField("yes");
    }
}

【讨论】:

  • 嗨苏格拉底,感谢您的建议。在这种情况下,我的 api 调用的请求映射是什么?还会是 GeneralPojoAllFields 吗?如果我有一个 {"firstName" : "bob", "lastName" : "sagget", "onlyAdminCanEditField" : "secret"} 的请求体,如果我将它用作 @RequetstBody 的一部分,它会在 GeneralPojo 中设置所有这些字段吗?现在我又回到了如果它是普通用户的困境。
  • 这取决于您的要求。您提到的示例 JSON 将是“GeneralPojoAllFields”对象,而不是“GeneralPojo”对象。它们在内部是相互连接的,但在外部它们看起来像两个对象,因为它们具有不同的特征。如果您请求您提到的 JSON 字符串并将其放入“GeneralPojo”对象中,您会因为反序列化失败而收到错误,或者您只是忽略了“onlyAdminCanEditField”并且只能访问“firstName”和“lastName”。跨度>
【解决方案2】:

首先,您的后端应尽可能独立于 UI。所以,UI 中的访问控制是一个很好的设计,但你不应该依赖它。

现在,回到您的问题,是的,您可以使用SecurityContextHolder 来确定用户是否为普通用户/管理员。但是,如果可能的话,我建议制作两个控制器,一个用于管理员,一个用于普通用户。在管理控制器上使用@PreAuthorize 来限制访问。拥有两个独立的控制器将极大地提高代码的可读性。

此外,您可以从两个控制器调用相同的服务类方法。由于您已经有两个 POJO 类,您可以在 @RequestBody 中使用它们,让 Spring 为您处理映射。

【讨论】:

  • 我也在考虑这个问题。我很好奇是否有一种方法可以根据角色重写来自请求的 url。例如,如果用户和管理员都向 /edit 发出请求,但在内部我们会向 user/edit 或 admin/edit 发出请求。
  • 是的,你可以。只需从控制器调用适当的服务方法。所以,如果你有这些服务方法,editServiceForUser()editServiceForAdmin();您可以做的是,在您的 /edit 控制器中调用其中任何一个用户的基本角色。
猜你喜欢
  • 2021-11-16
  • 2020-09-07
  • 2018-03-29
  • 2012-03-13
  • 2017-06-01
  • 2014-01-31
  • 1970-01-01
  • 1970-01-01
  • 2020-05-15
相关资源
最近更新 更多