springboot - blog project (60)

Yuri Lee·2020년 9월 2일
0

springboot - blog project

목록 보기
36/49

스프링부트 강좌 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에 들어가면 내 정보가 수정되지 않았다. 왜 일까?

데이터베이스의 값은 변경했지만 세션 값이 바뀌지 않았기 때문이다. 로그아웃을 하고 다시 로그인을 하면 알맞게 되어있을 것이다.

잘못된 건 아니고, 세션 값을 강제로 변경시키면 된다.

-이 글은 유투버 겟인데어의 스프링 부트 강좌를 바탕으로 정리한 내용입니다.-

profile
Step by step goes a long way ✨

0개의 댓글