2

Spring MVC には次のような問題があります。JSR 303 検証を使用して、Bean のプロパティ (以下の PasswordInfo を参照) が空でも null でもないことを確認します

また、2 つのパスワードが同一であるというビジネス ロジック ルールもチェックしています。

問題は、文字列フィールド (currentPassword および newPassword) の 1 つが空の場合でも、ビジネス ロジック ルールをチェックするためにコントローラーによってサービス層に渡され、もちろん IllegalArgumentException が発生することです。

ここにPasswordInfo豆があります:

@RooEquals
@RooJavaBean
public class PasswordInfo {

    @NotNull(groups = { ValidationGroups.PasswordModification.class })
    @NotEmpty(groups = { ValidationGroups.PasswordModification.class })
    private String currentPassword;

    @NotNull(groups = { ValidationGroups.PasswordModification.class, ValidationGroups.PasswordReset.class })
    @NotEmpty(groups = { ValidationGroups.PasswordModification.class, ValidationGroups.PasswordReset.class })       
    @Size(min = 6, groups = { ValidationGroups.PasswordModification.class, ValidationGroups.PasswordReset.class })
    private String newPassword;
...

関連するコントローラーメソッドは次のとおりです。

@RequestMapping(value = "/preference/password", method = RequestMethod.POST, produces = "text/html")
    public String modifyPassword(@ModelAttribute @Validated({ ValidationGroups.PasswordModification.class }) PasswordInfo passwordInfo,
            BindingResult bindingResult, Model model, @CurrentMember Member member) {
        if (!preferenceService.passwordsMatch(member.getPassword(), passwordInfo.getCurrentPassword())) {
            bindingResult.rejectValue("currentPassword", "controller.preference.wrong_current_password");
        }

        if (bindingResult.hasErrors()) {
            model.addAttribute("passwordInfo", passwordInfo);
            return "preference/password";
        }

        preferenceService.modifyPassword(member, passwordInfo.getNewPassword());
        return "redirect:/preference/password";
    }

関連するサービス層メソッドは次のとおりです。

@Override
    public boolean passwordsMatch(String encrypted, String plain) {
        if (encrypted == null || encrypted.isEmpty() || plain == null || plain.isEmpty()) {
            throw new IllegalArgumentException("One argument is null or empty");
        }
        return passwordEncoder.matches(plain, encrypted);
    }

私の懸念は、次のような別の bindingResults.hasErrors ブロックを配置しないようにすることです。

if (bindingResult.hasErrors()) {
        model.addAttribute("passwordInfo", passwordInfo);
        return "preference/password";
    }

...同じことを繰り返さないように、ビジネス ロジック チェックの前に...

誰でもこの問題のクリーンな解決策を提案できますか?

4

2 に答える 2

2

ここでの問題はBindingResult、パラメーターとして a を提供しているため、Spring MVC は、コントローラー メソッドで検証の問題を処理することを期待していることです。リクエストを完全に拒否するわけではありません (つまり、コントローラー メソッドの呼び出しを防ぎ、例外をスローします)。目的の結果を得るには、メソッドを再構築する必要があるだけです。

@RequestMapping(value = "/preference/password", method = RequestMethod.POST, produces = "text/html")
public String modifyPassword(@ModelAttribute @Validated({ ValidationGroups.PasswordModification.class }) PasswordInfo passwordInfo,
                             BindingResult bindingResult, Model model, @CurrentMember Member member) {
    String view = "preference/password";
    if (!bindingResult.hasErrors()) {
        if (preferenceService.passwordsMatch(member.getPassword(), passwordInfo.getCurrentPassword())) {
            preferenceService.modifyPassword(member, passwordInfo.getNewPassword());
            view = "redirect:/preference/password";
        } else {
            bindingResult.rejectValue("currentPassword", "controller.preference.wrong_current_password");
        }
    }
    // NOTE: I have removed the call to model.addAttribute("passwordInfo", passwordInfo) because it should already exist in the model, no?
    return view;
}
于 2013-10-08T01:27:27.557 に答える
0

私はあなたの例全体に従っているわけではなく、正直なところ、あなたの問題を完全には理解していませんが、私が疑問に思っていることの 1 つは、なぜパスワード一致制約にも Bean Validation を使用していないのですか? PasswordInfoのカスタム クラス制約を作成できます。

于 2013-10-07T09:40:24.793 に答える