Как предотвратить внедрение поля базы данных? - PullRequest
0 голосов
/ 19 февраля 2019

У меня есть модель , описанная следующим образом:

@Table
@Entity
@Data
@Builder
@ToString
@EqualsAndHashCode
@AllArgsConstructor
@NoArgsConstructor
public class User {
    // ...skipped...
    private String foo;
}

У меня также есть служба с методом, который создает новую сущность:

@Service
public class UserService {
    // ...skipped...
    public User createUser(User user) {
        Date currentDate = new Date();
        user.setCreated(currentDate);
        userRepository.save(user);
        return user;
    }
}

У меня также есть контроллер и сопоставленный метод:

@Controller
@RequestMapping(UserRouteRegistry.FIRST_LEVEL + "/*")
public class UserController {
    // ...skipped...
    @PostMapping(UserRouteRegistry.SIGN_UP)
    public String signUp(
            @ModelAttribute("user") @Validated(User.CreateUserGroup.class) User user,
            BindingResult result,
            WebRequest request,
            RedirectAttributes redirectAttributes
    ) {
    // ...mercellessly skipped...
                userRegistered = userService.createUser(user);
    // ...mercellessly skipped...
    }

Все довольно просто, верно?

У меня нетполе foo в веб-форме, и мне НЕ нужен веб-пользователь для установки этого поля, это должно быть какое-то действительно приватное поле, на которое НЕ должен напрямую влиять веб-пользователь.

КогдаЯ делаю собственный запрос POST, я вижу, что создается новый объект с полем foo, заполненным данными, которые были установлены в запросе:

POST /user/sign-up HTTP/1.1
Host: 127.0.0.1:8080
Origin:  http://127.0.0.1:8080
Content-Type: application/x-www-form-urlencoded
Referer:  http://127.0.0.1:8080/user/sign-up
Cookie:  SL_G_WPT_TO=ru; SL_GWPT_Show_Hide_tmp=1; SL_wptGlobTipTmp=1; BL_D_PROV=; BL_T_PROV=; JSESSIONID=E1190293BD183C647245BAE03E6DCDDA
cache-control: no-cache
Postman-Token: e572bccf-ff0a-4b0b-a181-dd0aa20dca99
foo=13
> SELECT foo FROM user ORDER BY id DESC LIMIT 1 \G
*************************** 1. row ***************************
foo: 13
1 row in set (0.0005 sec)

Да, это выглядит довольноправильно, но какой способ предотвратить что-нибудь?

Назначение "приватным" полям значения null на уровне service level?Это было бы довольно утомительно, но это сработало бы.Установка некоторого @annotation (кстати, какая аннотация должна быть?) Для этого поля на уровне model ?Я не уверен, что это было бы логично, по моему мнению.Фильтрация параметров на уровне контроллера , где-то перечислены все разрешенные параметры?Может быть, так?

Как правильно?

Спасибо!

Ответы [ 3 ]

0 голосов
/ 19 февраля 2019

Хорошей практикой является разделение модели и DTO - DTO, которые вы передаете между внешним и внутренним контроллерами, потому что иногда может быть намного больше, чем одно поле, которое нужно исключить или обработать по-разному.Также может быть так, что это поле необходимо в каком-то другом контексте, поэтому его нельзя исключить из самой модели.

Таким образом, пока ваш контроллер получает модель User, он должен получить UserDTO, который имеет только необходимыедопустимые поля.

Это, конечно, усложняет ситуацию, потому что вам нужно отобразить UserDTO между User.Но, к счастью, есть библиотеки для обработки, такие как ModelMapper .

0 голосов
/ 19 февраля 2019

Если вы публикуете данные формы , вы можете сделать это, как показано ниже, то есть, создав метод, аннотированный методом @InitBinder, а затем установив список запрещенных полей в предоставленном экземпляре WebDataBinder.

Этот метод может быть добавлен к вашему контроллеру, совету контроллера Spring MVC или к обоим.Для полей, общих для всех сущностей, вы можете добавить рекомендацию контроллера, а затем зарегистрировать дополнительные специфичные для сущности поля на соответствующем контроллере.

@InitBinder()
public void initBinder(WebDataBinder binder) {
    binder.setDisallowedFields(new String[] { "id", "version" });
}

Если вы публиковали данные JSON , вы могли бы сделать это с помощью аннотаций Джексона.Вы можете разместить их непосредственно в полях сущности или использовать классы смешения Джексона, чтобы избежать необходимости «загрязнять» модель предметной области проблемами веб-уровня.

Аннотируйте поле либо в сущности, либо в миксине:

@JsonProperty(access = Access.READ_ONLY)
private String myField;

Чтобы зарегистрировать миксин:

@Bean
public Jackson2ObjectMapperBuilderCustomizer addMixin(){
    return new Jackson2ObjectMapperBuilderCustomizer() {
        @Override
        public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
            jacksonObjectMapperBuilder.mixIn(User.class, UserMixin.class);                
        }
    };
}
0 голосов
/ 19 февраля 2019

Вы можете игнорировать это поле при десериализации

@JsonProperty(access = Access.READ_ONLY)
private String zaloopa;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...