스프링부트 강좌 60강(블로그 프로젝트) - 회원수정 1
회원정보
username은 수정할 수 없으니 readonly로 바꿈
email, password는 수정할 수 있음
header.jsp
<sec:authorize access="isAuthenticated()">
<sec:authentication property="principal" var="principal" />
</sec:authorize>
현재 세션으로 저장된 로그인한 객체가 principal이라는 이름으로 저장되어있다. 이것을 변수에 넣는다.
이 principal이 무엇이냐면..?
PrincipalDetail.java 에서 PrincipalDetail 이 var=principal 이다.
PrincipalDetail.java
package com.yuri.blog.config.auth;
import java.util.ArrayList;
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import com.yuri.blog.model.User;
import lombok.Getter;
// 스프링 시큐리티가 로그인 요청을 가로채서 로그인을 진행하고 완료가 되면 UserDetails 타입의 오브젝트를
// 스프링 시큐리티의 고유한 세션 저장소에 저장을 해준다.
@Getter
public class PrincipalDetail implements UserDetails{
private User user; //콤퍼지션: 객체를 품고 있는 것
//생성자
public PrincipalDetail(User user) {
this.user = user;
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUsername();
}
// 계정이 만료되지 않았는지 리턴한다. (true: 만료안됨)
@Override
public boolean isAccountNonExpired() {
return true;
}
// 계정이 잠겨있지 않았는지 리턴한다. (true: 잠기지 않음)
@Override
public boolean isAccountNonLocked() {
return true;
}
// 비밀번호가 만료되지 않았는지 리턴한다 (true: 만료안됨)
@Override
public boolean isCredentialsNonExpired() {
return true;
}
// 계정이 활성화(사용가능)인지 리턴한다 (true: 활성화)
@Override
public boolean isEnabled() {
return true;
}
// 계정이 갖고있는 권한 목록을 리턴한다. (권한이 여러개 있을 수 있어서 루프를 돌아야 하는데 우리는 한개만)
// 계정의 권한을 리턴한다.
// 컬렉션 타입?..
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
//왜 ArrayList..?
Collection<GrantedAuthority> collectors = new ArrayList<>();
collectors.add(()->{ return "ROLE_"+user.getRole();});
return collectors;
}
}
따라서 principal.user라고 하면 User 오브젝트에 접근할 수 있다. user.username, user.email 등 정보에 접근을 할 수 있다.
user.js
password와 email 만 받으면 어떤 user을 수정해야 할지 모른다. 그래서 hidden 값을 넣여주려고 한다.
@PutMapping("/user")
public ResponseDto<Integer> update(@RequestBody User user)
}
key=value, x-www-form-urlencoded를 받고 싶으면 @RequestBody를 사용하지 않아도 된다. 지금은 json 데이터를 받는 것이니까
우리가 지금 받은 유저는 외부로부터 받은 user이다. 수정할 때는 어떻게 하냐면 ...
혹시 몾찾을 수도 있으니까 , null 값일 수도 있으니까 orElseThrow를 걸어준다.
만약 찾았으면 여기에 오브젝트가 딱 들어올 것이다. 사용자로부터 패스워드를 받는다. rawPassword를 통해서.
근데 password를 암호화해서 넣어야 한다.
@Autowired
private BCryptPasswordEncoder encoder;
따라서 얘를 걸어준다. 얘를 걸면
UserService.java
package com.yuri.blog.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.yuri.blog.model.RoleType;
import com.yuri.blog.model.User;
import com.yuri.blog.repository.UserRepository;
//스프링이 컴포넌트 스캔을 통해서 Bean에 등록을 해줌. IoC를 해준다.
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private BCryptPasswordEncoder encoder;
@Transactional
public void 회원가입(User user) {
String rawPassword = user.getPassword(); //1234 원문
String encPassword = encoder.encode(rawPassword); // 해쉬
user.setPassword(encPassword);
user.setRole(RoleType.USER);
userRepository.save(user);
}
@Transactional
public void 회원수정(User user) {
// 수정시에는 영속성 컨텍스트 User 오브젝트를 영속화시키고, 영속화된 User 오브젝트를 수정
// select를 해서 User 오브젝트를 DB로부터 가져오는 이유는 영속화를 하기 위해서
// 영속화된 오브젝트를 변경하면 자동으로 DB에 update 문을 날려준다.
// 영속화니까 persistance 라고 하자
// 혹시 몾찾을 수도 있으니까 , null 값일 수도 있으니까 orElseThrow를 걸어줌
User persistance = userRepository.findById(user.getId()).orElseThrow(()->{
return new IllegalArgumentException("회원 찾기 실패");
});
String rawPassword = user.getPassword();
String encPassword = encoder.encode(rawPassword);
persistance.setPassword(encPassword); //password 수정해주기
persistance.setEmail(user.getEmail()); //영속화 되어있는 곳에서 setEmail를 통해 변경해준다
// 회원수정 함수 종료시 = 서비스 종료 = 트랜잭션 종료 = commit이 자동으로 된다는 의미이다.
// commit 이 자동으로 된다는 것은 영속화된 persistance 객체의 변화가 감지되면, 더티체킹이 되어 변화된 것들을 업데이트 update 문을 자동으로 날려준다.
}
}
회원수정 함수가 종료되면 이 persistance의 값이 변경 되었으니까 db에 변경된 update 문을 날리고 commit이 이루어진다. 그럼 회원수정이 될 것이다.
비밀번호를 1234 -> 1111
이메일을 user@nate.com -> user.gmail.com 으로 바꿨다. 디비에 잘 들어가 있는 모습을 확인할 수 있다.
하지만 다시 myinfo에 들어가면 내 정보가 수정되지 않았다. 왜 일까?
데이터베이스의 값은 변경했지만 세션 값이 바뀌지 않았기 때문이다. 로그아웃을 하고 다시 로그인을 하면 알맞게 되어있을 것이다.
잘못된 건 아니고, 세션 값을 강제로 변경시키면 된다.
-이 글은 유투버 겟인데어의 스프링 부트 강좌를 바탕으로 정리한 내용입니다.-