회원정보 수정 기능은 사용자의 입력 값으로 DB의 정보를 최신화 시킨 다음

최신화된 DB정보를 바탕으로 스프링 시큐리티의 로그인 로직을 내부적으로 실행시켜 세션의 로그인 정보를 최신화 하는 방법으로 구현되었습니다.

/user/updateForm.html

외부 자바스크립트 코드를 통하여 Ajax 통신을 진행할 것이기 때문에 button을 form태그 밖에서 작성합니다.

input 태그의 id 값을 통해 입력값과 외부 자바스크립트 변수를 매핑해 줄 것 입니다.

<div class="container" style="margin-bottom: 1rem">

    <form>
        <div class="mb-3 mt-3">
            <label for="username" class="form-label">UserName:</label>
            <input type="text" class="form-control" id="username" 
                   th:value="${#authentication.principal.user.username}" 
                   name="username" readonly>
        </div>

        <div th:if="${#authentication.principal.user.oauth == null}" class="mb-3">
            <label for="password" class="form-label">Password:</label>
            <input type="text" class="form-control" id="password" 
                   placeholder="Enter password" name="password">
        </div>

        <div th:if="${#authentication.principal.user.oauth == null}" class="mb-3 mt-3">
            <label for="email" class="form-label">Email:</label>
            <input type="email" class="form-control" id="email" 
									 th:value="${#authentication.principal.user.email}" 
                   placeholder="Enter email" name="email">
        </div>

        <div th:unless="${#authentication.principal.user.oauth == null}" 
                class="mb-3 mt-3">
            <label for="email" class="form-label">Email:</label>
            <input type="email" class="form-control" 
                   th:value="${#authentication.principal.user.email}" 
                   placeholder="Enter email" name="email" readonly>
        </div>
    </form>
    <button id="btn-update" class="btn btn-primary">회원정보 수정</button>
</div>

<script type="text/javascript" th:inline="javascript">
    const updateUserId = $.parseJSON('[[ ${#authentication.principal.user.id} ]]');
</script>

user.js

/user 로 HttpBodyjson 형식으로 데이터를 담아 PUT 요청을 보냅니다.

update: function (){
    let data = {
        id: updateUserId,
        username: $("#username").val(),
        password: $("#password").val(),
        email: $("#email").val()
    }

    $.ajax({
        type: "PUT",
        url: "/user",
        data: JSON.stringify(data),
        contentType: "application/json; charset=utf-8",
        dataType: "json",

    }).done(function (response) {
        // 요청 결과가 정상인 경우
        const status = response.status;

        if (status === 200){
            alert("회원정보 수정이 완료 되었습니다.");
            location.href = ("/");
        } else {
            alert(response.data);
        }

    }).fail(function (error) {
        // 요청 결과가 비정상인 경우
        alert(JSON.stringify(error));

    }); // ajax 통신을 이용해서 3개의 데이터를 json 으로 변경하여 insert 요청
}

UserApiController.java

회원 정보를 수정했을 시 스프링시큐리티 내부에서 새로운 정보를 토대로 재로그인이 실행되고 최신의 정보가 세션에 저장될 수 있도록 코드를 작성합니다.

@PutMapping("/user")
public ResponseDTO<Integer> update(@RequestBody User user){
    userService.update(user);
    // 서비스가 종료되면서 트랜잭션도 종료되어 DB의 값은 변경되지만
    // 시큐리티 세션의 정보는 변경 되지 않은 상태이기 때문에 직접 세션의 값 변경이 필요하다.
    Authentication authentication = authenticationManager.authenticate(
            new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()));
    SecurityContextHolder.getContext().setAuthentication(authentication);

    return new ResponseDTO<Integer>(HttpStatus.OK.value(), 1);
}

UserService.java

새로운 User 객체를 생성하여 영속화 시킵니다.

이후 요청된 값의 유효성을 체크한 뒤 트랜잭션을 종료시키며 데이터베이스에 Commit 합니다.

@Transactional
public void update(User requestUser) {
    User persistenceUser = userRepository.findById(requestUser.getId()).orElseThrow(() -> {
        throw new IllegalArgumentException("회원수정 실패: 회원 정보가 존재하지 않습니다.");
    });

    //validate 체크
    if (persistenceUser.getOauth() == null || persistenceUser.getOauth().equals("")) {
        persistenceUser.setPassword(encoder.encode(requestUser.getPassword()));
        persistenceUser.setEmail(requestUser.getEmail());
    }
}