在DTO类中限制字段访问并返回不同的值。

huangapple go评论53阅读模式
英文:

Restrict acces in DTO class for fields and return different value

问题

我正在我的Spring Boot应用程序中实现授权功能。我希望将授权应用到DTO(数据传输对象)中。

请查看下面的类:

public class ExampleDTO{
    private String phoneNumber; // 希望限制对此字段的访问。
}

例如:

用户A拥有权限A,可以看到手机号码123456789
用户B拥有权限B,可以看到手机号码123456***

一个解决方案可以是这样的:

public void setPhoneNumber(String iban) {
    if (Service.checkPermission("A")) {
        this.phoneNumber = "123456789";
    } else if (Service.checkPermission("B")) {
        this.phoneNumber = "123456***";
    } else {
        this.phoneNumber = "*********";
    }
}

但这违反了面向对象编程的原则。

另外,我可以在一个服务中执行这个操作:

public ExampleDTO getExampleDto(String iban) {
    if (checkPermission("A")) {
        return ExampleDtoA;
    } else if (checkPermission("B")) {
        return ExampleDtoB;
    } else {
        return ExampleDtoC;
    }
}

但这会导致代码重复。

那么,你们有更好的解决方案吗?

英文:

I'm implementing authorization in my Spring Boot application. And I want to apply authorization to dto's.

See the class below

public class ExampleDTO{
    private String phoneNumber; // want to restrict acces on this field.
}

E.g.

User A with permission A can see phoneNumber 123456789
User B with permission B can see phoneNumber 123456***

A solutions can be something like this:

public void setPhoneNumber(String iban) {
    if (Service.checkPermission("A")) {
        this.phoneNumber= 123456789;
    } else if (Service.checkPermission("B")) {
        this.phoneNumber= "123456***";
    } else {
        this.phoneNumber= "*********";
    }
}

But this is against the OOP principle.

Also I can do this in a service:

public ExampleDTO getExampleDto(String iban) {
    if (checkPermission("A")) {
        return ExampleDtoA;
    } else if (checkPermission("B")) {
        return ExampleDtoB;
    } else {
        return ExampleDtoC;
    }
}

But this will allow code duplication;

So does one of you have a better solution?

答案1

得分: 0

使用构建器来构建 ExampleDto 的一种方法是这样的:

public class ExampleDTOBuilder {

    public enum PhonePermission { A, B, NONE };
    
    private String phoneNumber;
    private PhonePermission phonePermission = PhonePermission.NONE;
    
    public ExampleDTOBuilder setPhoneNumber( String phoneNumber ) {
        this.phoneNumber = phoneNumber;
        return this;
    }
    
    public ExampleDTOBuilder setPermission(PhonePermission phonePermission) {
        this.phonePermission = phonePermission;
        return this;
    }
    
    public ExampleDTO build() {
        ExampleDTO dto = new ExampleDTO();
        
        switch (this.phonePermission) {
        case A:
            dto.setPhoneNumber(this.phoneNumber);
            break;
        case B:
            dto.setPhoneNumber(getMaskedPhoneNumber(this.phoneNumber));
        default:
            dto.setPhoneNumber("********");
            break;
        }
        
        return dto;
    }
    
    private String getMaskedPhoneNumber(String phoneNumber) {
        return "123***"; // 进行您的脱敏处理
    }
}

使用示例:

ExampleDTO dto = new ExampleDTOBuilder()
        .setPermission(ExampleDTOBuilder.PhonePermission.A)
        .setPhoneNumber("123456")
        .build();

有关构建器模式的更多详细信息,请参阅此处:https://en.wikipedia.org/wiki/Builder_pattern

英文:

One way to go is to use a builder to build ExampleDto. Something like this:

public class ExampleDTOBuilder {

    public enum PhonePermission { A, B, NONE };
    
    private String phoneNumber;
    private PhonePermission phonePermission = PhonePermission.NONE;
    
    public ExampleDTOBuilder setPhoneNumber( String phoneNumber ) {
        this.phoneNumber = phoneNumber;
        return this;
    }
    
    public ExampleDTOBuilder setPermission(PhonePermission phonePermission) {
        this.phonePermission = phonePermission;
        return this;
    }
    
    public ExampleDTO build() {
        ExampleDTO dto = new ExampleDTO();
        
        switch (this.phonePermission) {
        case A:
            dto.setPhoneNumber(this.phoneNumber);
            break;
        case B:
            dto.setPhoneNumber(getMaskedPhoneNumber(this.phoneNumber));
        default:
            dto.setPhoneNumber("********");
            break;
        }
        
        return dto;
    }
    
    private String getMaskedPhoneNumber(String phoneNumber) {
        return "123***"; // do your masking
    }
}

Use:

ExampleDTO dto = new ExampleDTOBuilder()
        .setPermission(PhonePermission.A)
        .setPhoneNumber("123456")
        .build();

More details about the Builder pattern can be found here: https://en.wikipedia.org/wiki/Builder_pattern

答案2

得分: 0

我假设您将这些电话号码保存在数据库中,并且希望根据权限返回不同的值。

如果是这种情况,那么您不应该修改DTO的setPhoneNumber方法,因为这可能会将以下电话号码值放入您的数据库:123456************

您可以在实体和DTO层之间封装逻辑,使用一个转换器:

public class ExampleService {
    ExampleDto getExample(String iban) {
        // 从数据库获取实体
        ExampleEntity entity = entityRepository.getEntity(iban);
        return converter.convert(entity);
    }
}
public class Converter {
    public ExampleDto convert(ExampleEntity entity) {
        ExampleDto dto = new ExampleDto();
        if (checkPermission("A"))
            dto.setPhoneNumber(entity.getPhoneNumber());
        else if (checkPermission("B"))
            dto.setPhoneNumber(entity.getPhoneNumberPartialMasked());
        else
            dto.setPhoneNumber(entity.getPhoneNumberMasked());
        return dto;
    }
}

如果您正在使用Spring框架,那么您可以查看以下类:org.springframework.core.convert.converter.Converterorg.springframework.core.convert.ConversionService。关于如何使用这些类,有许多示例可以参考。

英文:

I am assuming that you are saving these phone numbers in a database and that you want to persist the real phone numbers, but return different values based on permissions.

If this is the case, then you should not alter the setPhoneNumber method of the DTO as this could put the following phone number values into your DB: 123456***, *********.

You can encapsulate the logic in a converter between your entity and dto layer

public class ExampleService {
    ExampleDto getExample(String iban) {
        // Get entity from your DB
        ExampleEntity entity = entityRepository.getEntity(iban);
        return converter.convert(entity);
    }
}
public class Converter {
    public ExampleDto convert(ExampleEntity entity) {
        ExampleDto dto = new ExampleDto();
        if (checkPermission("A"))
            dto.setPhoneNumber(entity.getPhoneNumber());
        else if (checkPermission("B"))
            dto.setPhoneNumber(entity.getPhoneNumberPartialMasked();
        else
            dto.setPhoneNumber(entity.getPhoneNumberMasked());
        return dto;
    }
}

If you are using the spring framework, then you can see the following classes: org.springframework.core.convert.converter.Converter and org.springframework.core.convert.ConversionService. There are lots of examples out there on how to use these.

huangapple
  • 本文由 发表于 2020年9月30日 22:34:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/64139857.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定