기술 공부

패스워드 암호화

랼랼 2022. 4. 11. 22:02

 

Email security vector created by macrovector - www.freepik.com

 

1. UserService 에서

public UserEntity getByCredentials(
	final String email, final String password, final PasswordEncoder encoder) {
    
    final UserEntity originalUser=userRepository.findByEmail(email);
    //matches 메서드 이용하여 salt를 고려하여 패스워드가 같은지 확인
    if(originalUser!=null&&encoder.matches(password, originalUser.getPassword())) {
        return originalUser;
    }
    return null;
}

email(고유 id)를 통해 UserEntity를 가져온 뒤,

encoder한 password와 현재 password가 서로 match 되는지를 확인한 뒤 UserEntity 객체를 리턴한다.

여기서 matches를 사용하는 이유는 인코더의 과정에 있다.

우리가 사용할 encoder는 BCrytPasswordEncoder를 사용할텐데

이를 사용하여 패스워드를 인코딩하게 되면, 인코딩 된 패스워드에 Salt라는 의미없고 랜덤한 문자들이 붙게된다.

따라서 같은 패스워드를 인코딩하게 되어도, Salt때문에 완전히 같지는 않다.

encoder의 matches는 이 Salt를 고려하여 두 값의 일치 여부를 판별해준다.

 

2. UserController에서

package com.example.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.example.demo.dto.ResponseDTO;
import com.example.demo.dto.UserDTO;
import com.example.demo.model.UserEntity;
import com.example.demo.security.TokenProvider;
import com.example.demo.service.UserService;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestController
@RequestMapping("/auth")
public class UserController {
	@Autowired
	private UserService userService;
	
	@Autowired
	private TokenProvider tokenProvider;
	
	//패스워드 암호와를 위한 엔코더
	private PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
	
	//회원 가입
	@PostMapping("/signup")
	public ResponseEntity<?> responseUser(@RequestBody UserDTO userDTO){
		try {
			//요청을 이용해 저장할 사용자 만들기
			UserEntity user = UserEntity.builder()
					.email(userDTO.getEmail())
					.user(userDTO.getUser())
					//비밀번호를 엔코더해서 저장
					.password(passwordEncoder.encode(userDTO.getPassword()))
					.build();
			
			log.info(userDTO.getPassword());
			
			//서비스를 이용해 리포지터리에 저장
			UserEntity registeredUser = userService.create(user);
			//유저정보 가져오기 (1개)
			UserDTO responsedUser = UserDTO.builder()
					.email(registeredUser.getEmail())
					.id(registeredUser.getId())
					.user(registeredUser.getUser())
					.build();
			//ok 리턴
			return ResponseEntity.ok().body(responsedUser);
					
		} catch (Exception e) {
			//에러 시 에러 메세지 발생
			ResponseDTO responseDTO = ResponseDTO.builder().error(e.getMessage()).build();
//			log.warn("controller : "+e.getMessage());
			return ResponseEntity.badRequest().body(responseDTO);
		}
	}
	//로그인
	@PostMapping("/signin")
	public ResponseEntity<?> authenticate(@RequestBody UserDTO userDTO){
		UserEntity user = userService.getByCredentials(
        	userDTO.getEmail(), userDTO.getPassword(),passwordEncoder);
		if(user!=null) {
			//토큰 생성
			final String token = tokenProvider.create(user);
			final UserDTO responseUserDTO = UserDTO.builder()
					.email(user.getEmail())
					.id(user.getId())
//					.user(user.getUser())
					.token(token)
					.build();
			return ResponseEntity.ok(responseUserDTO);
		} else {
			ResponseDTO responseDTO = ResponseDTO.builder()
					.error("Login failed.")
					.build();
			return ResponseEntity.badRequest().body(responseDTO);
		}
	}
	
}

1) 비밀번호를 Entity에 build 시, 인코더를 이용하여 인코딩한 비밀번호를 저장한다.

2) 로그인 시 서비스에서 선언한 getByCredentials를 이용하여 해당 회원이 맞는지를 판별한다.

반응형