spring-bootvue.jsaxios

Required String parameter 'newPassword' is not present


SOLVED

We've solved it. The form that the backend requires data was param, so the form that the vue sends was changed to param, not data!


I'm making a password change page. Meanwhile, I got an error that there was no old password, new password data but I definitely transferred the data from Vue through axios.

There were answers to 'required=false', so I tried oldpassword, but here's the result.

enter image description here

enter image description here

However, we took 'required= true' because we believe newpassword, oldpassword is essential data for this approach. When using post-man or swagger, the password is changed signaling 200 normally.

I thought there might be a problem with 'patch', so I tried 'put', but the error didn't change.

frontend

<div class="input-with-label">
    <input v-model="newpassword" id="newpassword" placeholder="새 비밀번호를 입력하세요." :type="passwordType"  />
    <label for="newpassword">새 비밀번호</label>
    <div class="error-text" v-if="error.newpassword">{{error.newpassword}}</div>
</div>

<form @submit.prevent="changepassword" @submit="checkForm">
    <div v-if="activeButton() && !isSubmit">
        <!-- <button @click="PopUpEmailModal" class="btn-bottom" >가입하기</button> -->
        <button class="btn-bottom">변경하기</button>
    </div>
    <div v-else>
        <button class="btn-bottom disabled" >변경하기</button>
    </div>
</form>
import axios from 'axios'
export default {
  name:'ChangePassword',
  data: ()=> {
    return{
      email:"",
      oldpassword:"",
      newpassword:"",
      isSubmit: true,
      error: {
        newpassword: false,
      },
      passwordType: "password",
      passwordSchema: new PV(),
    }
  },
  created() {
    this.passwordSchema
      .is()
      .min(8)
      .is()
      .max(100)
      .has()
      .digits()
      .has()
      .letters();
  },
  watch: {
    newpassword: function(v) {
      this.checkForm();
    },
  },
  methods:{
    changepassword(){
        axios({
          url:'http://127.0.0.1:8080/account/changePassword',
          method:'patch',
          data:{
            email: this.email,
            oldPassword: this.oldpassword,
            newPassword: this.newpassword,
          },
        })
          .then(res=>{
            console.log(res)
            this.$router.push({ name:'Login' })
          })
          .catch(err=>{
            console.log(typeof this.oldpassword)
            console.log(this.oldpassword)
            console.log(this.newpassword)
            console.log(this.email)
            console.log(err)
          })
    },
  }

backend

@PatchMapping("/account/changePassword")
    @ApiOperation(value = "비밀번호변경")
    public Object changePassword(@RequestParam(required = false) final String oldPassword,
                                 @RequestParam(required = true) final String newPassword,
                                 @RequestParam(required = true) final String email){
        Optional<User> userOpt = userDao.findByEmail(email);
        if(!passwordEncoder.matches(oldPassword, userOpt.get().getPassword())){
            throw new IllegalArgumentException("잘못된 비밀번호입니다.");
        }
        User user = new User(userOpt.get().getUid(), userOpt.get().getNickname(), email,
                passwordEncoder.encode(newPassword), userOpt.get().getIntroduction(), userOpt.get().getThumbnail(), userOpt.get().getRoles());
        userDao.save(user);
        final BasicResponse result = new BasicResponse();
        result.status = true;
        result.data = "success";
        ResponseEntity response = null;
        response = new ResponseEntity<>("OK", HttpStatus.OK);
        return response;
    }

Solution

  • I believe you are using @RequestParam annotations but you are not sending any params in the URL from the frontend, hence the 400 error.

    Since you are using Patch/Put I would suggest you change your changePassword function to take a dto. And since you are already sending data in the body from frontend so no change needed there.

    For example

    public Object changePassword(@RequestBody @Valid ChangePasswordDto changePasswordDto){
    // your logic 
    }
    

    Then create a ChangePasswordDto class with @Required on properties that are required.

    public class ChangePasswordDto{
     
        private String email;    
        private String newPassword;
        private String oldPassword;
        
        @Required
        public void setEmail(String email) {
            this.email= email;
        }
    
        @Required
        public void setOldPassword(String oldPassword) {
            this.oldPassword= oldPassword;
        }
        @Required
        public void setNewPassword(String newPassword) {
            this.newPassword= newPassword;
        }
    
        // corresponding getters
    }