ํ์์ ๋ณด๋ ํ์ฌ ๋ก๊ทธ์ธ๋ ์ ์ , ์ฆ ์ธ์ ์์ ๋ค๊ณ ์ค๋ฉด ๋๋ค. ํค๋์ ์ํ๋ฆฌํฐ ํ๊ทธ๋ก "pricipal" ๋ณ์์ ํ์ฌ ์ธ์ ์ ๋ณด ๋ฃ์ด ๋์๊ธฐ ๋๋ฌธ์ ์ด ๋ณ์ ์ฐ๋ฉด ๋๋ค. (select ํ ํ์ X)
< updateForm.jsp >
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ include file="../layout/header.jsp"%>
<div class="container">
<form>
<input type="hidden" id="id" value="${principal.user.id}" />
<div class="form-group">
<label for="username">Username</label>
<input type="text" value="${principal.user.username}" class="form-control" placeholder="Enter username" id="username" readonly>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" placeholder="Enter password" id="password">
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" value="${principal.user.email}" class="form-control" placeholder="Enter email" id="email">
</div>
</form>
<button id="btn-update" class="btn btn-primary">ํ์์์ ํ๊ธฐ</button>
</div>
<script src="/js/user.js"></script>
<%@ include file="../layout/footer.jsp"%>
์๋จ๋ฐ "ํ์์ ๋ณด" ๋ฒํผ์ /user/updateForm
url์ ๊ฑธ์ด๋๋ค. ์ด ๋ฒํผ์ ๋๋ฅด๋ฉด ํด๋น url๋ก ์ด๋ํ ๊ฒ์ด๋ค.
id๋ ์ถํ์ DB์์ select ํ๊ธฐ ์ํด hidden์ผ๋ก ๋ง๋ค์ด์ฃผ๊ณ , Username์ ๋ณ๊ฒฝํ ์ ์๋๋ก input์ readonly ์์ฑ์ ๋ฃ๋๋ค.
< UserController >
@GetMapping("/user/updateForm")
public String updateForm() {
return "user/updateForm";
}
id="btn-update"์ธ ํ์ ์์ ๋ฒํผ์ ๋๋ฅด๋ฉด user.js๊ฐ ์๋ํ๋ค.
< user.js >
.
.
.
$("#btn-update").on("click", ()=>{ // function(){} ๋์ ()=>{} ๋ฅผ ์ด ์ด์ : this๋ฅผ ๋ฐ์ธ๋ฉํ๊ธฐ ์ํด์
this.update();
});
.
.
.
update: function () {
let data = {
id: $("#id").val(),
username: $("#username").val(),
password: $("#password").val(),
email: $("#email").val()
};
$.ajax({
type: "PUT",
url: "/user",
data: JSON.stringify(data), // http body ๋ฐ์ดํฐ
contentType: "application/json; charset=utf-8", // body ๋ฐ์ดํฐ๊ฐ ์ด๋ค ํ์
์ธ์ง (MIME)
dataType: "json" // ์์ฒญ์ ์๋ฒ๋ก ํด์ ์๋ต์ด ์์ ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ชจ๋ ๊ฒ์ด String(๋ฌธ์์ด), ๋ง์ฝ ์๊ธด๊ฒ json์ด๋ผ๋ฉด javascript ์ค๋ธ์ ํธ๋ก ๋ณ๊ฒฝ
}).done(function (resp) {
// ๊ฒฐ๊ณผ๊ฐ ์ ์์ด๋ฉด done ์คํ
alert("ํ์์์ ์ด ์๋ฃ๋์์ต๋๋ค.");
//console.log(resp);
location.href = "/";
}).fail(function (error) {
// ์คํจํ๋ฉด fail ์คํ
alert("ํ์์์ ์ด ์คํจํ์์ต๋๋ค.");
alert(JSON.stringify(error));
});
}
.
.
.
์์ ์ด๊ธฐ ๋๋ฌธ์ ํ์
์ PUT ์ผ๋ก ํ์ฌ /user
์ ๋ฐ์ดํฐ๋ฅผ ๋๊ธด๋ค. (json ํ์
์ผ๋ก)
< UserApiController >
@PutMapping("/user")
public ResponseDto<Integer> update(@RequestBody User user) { // id, password, email
userService.ํ์์์ (user);
return new ResponseDto<Integer>(HttpStatus.OK.value(), 1); // ํต์ ์ฑ๊ณต : 200, ์คํจ : 500 // ์๋ฐ ์ค๋ธ์ ํธ๋ฅผ JSON์ผ๋ก ๋ณํํด์ ๋ฆฌํด (Jackson)
}
< UserService >
@Transactional // ์ ์ฒด๊ฐ ์ฑ๊ณตํด์ผ commit, ์คํจํ๋ฉด rollback
public void ํ์์์ (User user) {
// ์์ ์์๋ JPA ์์์ฑ ์ปจํ
์คํธ์ User ๊ฐ์ฒด๋ฅผ ์์ํ ์ํค๊ณ , ์์ํ๋ User ๊ฐ์ฒด๋ฅผ ์์ ํ๋ฉด ๋๋ค.
// select ํ์ฌ DB์์ ๊ฐ์ ธ์ ์์ํ๋ฅผ ํ๋ค.
// ์์ํ๋ ๊ฐ์ฒด๋ฅผ ๋ณ๊ฒฝํ๋ฉด ์๋์ผ๋ก ๋ณ๊ฒฝ๊ฐ์ง๋์ด (๋ํฐ์ฒดํน) DB์ update ๋๋ค. (flush)
User persistance = userRepository.findById(user.getId()) // select ํ์ฌ ์์ํ
.orElseThrow(()->{
return new IllegalArgumentException("ํ์์ด ์กด์ฌํ์ง ์์ต๋๋ค. id : "+user.getId());
});
String rawPassword = user.getPassword();
String encPassword = encoder.encode(rawPassword);
persistance.setPassword(encPassword); // ์์ํ ๋์ด ์๋ ๊ฐ์ฒด๋ฅผ ๋ณ๊ฒฝ
persistance.setEmail(user.getEmail());
// ํ์ ์์ ํจ์ ์ข
๋ฃ ์(Service ์ข
๋ฃ ์) -> ํธ๋์ญ์
์ข
๋ฃ -> commit(์๊ตฌ์ )์ด ์๋์ผ๋ก ๋๋ค.
// ์์ํ๋ persistance ๊ฐ์ฒด์ ๋ณํ๊ฐ ๊ฐ์ง๋๋ฉด ๋ํฐ์ฒดํน ๋์ด ์๋์ผ๋ก DB์ update๋ฌธ์ ๋ ๋ ค์ค๋ค.
}
์๋น์ค์๋ ํธ๋์ญ์
์ ๊ฑด๋ค.
๊ทธ๋ฌ๋ฉด DB์์ selectํ ๊ฐ์ฒด๋ฅผ ์์์ฑ ์ปจํ
์คํธ์ ์์ํ ์ํค๊ณ , ์์ํ ๋์ด ์๋ ๊ฐ์ฒด๋ฅผ ๋ณ๊ฒฝํ๋ฉด ๋๋ค.
๊ทธ๋ฌ๋ฉด ํธ๋์ญ์
์ด ๋๋ ํ ๋ค์ ๋งํด์ Service๊ฐ ๋๋ ํ์ ๋ํฐ์ฒดํน์ ํ์ฌ DB์ ๋ณ๊ฒฝ๋ ๋ฐ์ดํฐ๊ฐ flush ๋ ๊ฒ์ด๋ค.
ํ์ฌ ์ํ๋ ํ์์์ ์ ํ๋ฉด DB ๋ฐ์ดํฐ๋ ๋ฐ๋์ง๋ง, ์ธ์
์ ๋ฐ๋์ง ์์๋ค.
๋ค์ ํ์์์ ์ ๋ค์ด๊ฐ๋ฉด ๋ฐ๊พธ๊ธฐ ์ ๋ฐ์ดํฐ๊ฐ ๋ํ๋ ๊ฒ์ด๋ค.
(๋ฌผ๋ก ๋ฐ์ดํฐ๋ DB์ ๋ฐ๋์ด ์์ง๋ง!!)
๋ฐ๋ผ์ ํ์์์ ์ ํ๋ฉด ์ธ์
๊ฐ(ํ์ฌ ๋ก๊ทธ์ธ ๋์ด ์๋)๋ ๋์์, ์ฆ์(?) ๋ฐ๋์ด์ผ ํ๋ค.
์ธ์
์์ ์ํ๋ฆฌํฐ ์ปจํ
์คํธ์ Authentication ๊ฐ์ฒด๋ฅผ ๊ฐ์ ๋ก ๋ฃ์ด์ฃผ๋ ๊ฒ์ด๋ค. (์ํ๋ฆฌํฐ ์ปจํ
์ค๋ Authentication๋ง ๊ฐ๋ฅ)
< SecurityConfig >
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
AuthenticationManager ๊ฐ Authentication ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ธฐ ๋๋ฌธ์ ์ด Manager๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด ๋น์ผ๋ก ๋ฑ๋กํด์ผ ํ๋ค.
< UserApiController >
.
.
.
// ์ธ์
๋ฑ๋ก (DB๊ฐ ๋ณ๊ฒฝ๋ ํ์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์์ผ ํ๋ฏ๋ก Service๊ฐ ๋๋ ํ(=ํธ๋์ญ์
๋๋ ํ)์ ์ด๋ฃจ์ด์ ธ์ผ ํ๋ค. ๋ฐ๋ผ์ Controller์์ ์งํ
Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
.
.
.
Service๊ฐ ๋๋๊ณ ํธ๋์ญ์ ์ด ๋๋๊ณ DB์ ๋ณ๊ฒฝ์ด ๋ฐ์๋ ํ์ ์ด๋ฃจ์ด์ ธ์ผ ํ๊ธฐ ๋๋ฌธ์ UserApiController์์ ์งํํ๋ค.
ํ๋ฆ์ ์์ฒ๋ผ ๋๋ค.
์ธ์ ์ ๋ฑ๋กํ๊ธฐ ์ํด์๋ HttpSession์ SecurityContextHolder - SecurityContext ์์ Authentication ๊ฐ์ฒด๋ฅผ ๋ฑ๋กํด์ผ ํ๋ค.
๋ด๊ฐ ๊ฐ์ ๋ก Authentication ๊ฐ์ฒด๋ฅผ ๋ง๋ค ์ ์์ผ๋ฏ๋ก AuthenticationManager ๋ฅผ ํตํด Authentication ๊ฐ์ฒด๋ฅผ ์์ฑํด์ผ ํ๋ค.
AuthenticationManager ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด SecurityConfig์ ์์ฑ ํ ๋น์ผ๋ก ๋ฑ๋กํ์ฌ, ์คํ๋ง์ด IoC๋ก ๊ด๋ฆฌํ๊ฒ ํ๋ค.
AuthenticationManager ๋ฅผ ํ์ฉํ์ฌ, ์์ ๋(Service์์ ์์ ๋๊ณ DB ๋ณ๊ฒฝ๊น์ง ์๋ฃ๋) User ๊ฐ์ฒด์ username ๊ณผ password๋ก ์๋ก์ด ํ ํฐ์ ๋ง๋ค์ด์ Authentication ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค.
Authentication ๊ฐ์ฒด๋ฅผ ๋ง๋ค ๋ ํ์ํ ์กฐ๊ฑด์ DB์ ํด๋น ์ ์ ๊ฐ ์์ด์ผ ํ๋ค.
๋ฐ๋ผ์ username์ UserDetailService์ ๋์ง๊ณ , UserDetailService๊ฐ DB์ ์ ๊ทผํ์ฌ ํ์ธํ๋ค. ์ด๊ฑธ ํ ๋๋ก ๋น๋ฐ๋ฒํธ๋ ํ์ธํด์ผ ํ๋ค.
AuthenticationManager ๊ฐ ์ด์ password๋ฅผ BCrypt๋ก ์ธ์ฝ๋ฉํ์ฌ DB์ ๋ค์ ํ์ธํ ํ, ๋ง์ผ๋ฉด Authentication ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค.
HttpSession์ SecurityContextHolder ์์ SecurityContext ์์ ์๋ Authentication ๊ฐ์ฒด๋ฅผ ์ฐ๋ฆฌ๊ฐ ๋ง๋ ์๋ก์ด Authentication์ผ๋ก ๋ฎ๋๋ค. ์ฆ, ๊ธฐ์กด์ ์ธ์ ๊ฐ์ ์๋ก ๋ง๋ ๊ฐ(์๋ก ๋ง๋ค์ด์ง Authentication ๊ฐ์ฒด)์ผ๋ก ๋ณ๊ฒฝํ๋ค.
์ต์ข ์ ์ผ๋ก ์ํ๋ฆฌํฐ ์ปจํ ์คํธ์ ๋ฃ์ด์ง ๊ฒ์ด๋ค.