본문 바로가기
혼자서 개발새발

Spring) 회원가입 비밀번호 암호화를 도전해보자!

by 휴일이 2022. 11. 16.

 

DB에 비밀번호를 그대로 저장하면 곤란하니까

비밀번호를 암호화해서 저장하고

로그인할 땐 복호화할 수 있도록 기능을 추가해보자!

 

BCryptPasswordEncoder 클래스를 이용했다!

 

 

 

일단 회원가입!

1) 객체를 받은 후

2) 비밀번호만 따로 인코딩해서 다시 객체에 넣어준다

3) 그 정보를 DB에 넣는다

 

 

 

 

Controller

	@Autowired
	BCryptPasswordEncoder passwordEncoder;
    
	@PostMapping("/signUp") // /hi/signUp
	@ResponseBody
	public String signUpTest(@RequestBody MemberDto dto) throws Exception {
		//받은 객체의 pwd를 인코더로 변환 후, 수정한다
		String pwd = pwdEncode(dto.getPwd());
		dto.setPwd(pwd);
		//sql문으로 insert
		int num = service.signUp(dto);
		// insert가 동작했는지 알아보기 위해 출력
		System.out.println("num = " + num);
		String result = "";
		if(num==1) {
			result = "SignUp OK";
			return result;
		}
		result="SignUp ERR";
		return result;
	}

 

 

비밀번호 암호화 메서드

	public String pwdEncode (String pwd) {
		String password = passwordEncoder.encode(pwd);
		System.out.println("password = " + password);
		return password;
	}

 

 

 

매핑 SQL문

ㄴ 특수문자를 포함하니까, CDATA로 감싸주었다(특수문자 포함 가능하게 하는 MyBatis 기능)

ㄴ 이거 안 해도 되는 거 같다...ㅎㅎ 그냥 && 이나 이런 거 쓸 때 넣는 거인듯

    <insert id="insert" parameterType="MemberDto">
        <![CDATA[INSERT INTO member_info
                     (id, pwd, name, email, birth, reg_date)
                 VALUES
                     (#{id}, #{pwd}, #{name}, #{email}, now(), now())]]>
    </insert>

 

 

 

 

하지만 이렇게 요리조리 수정을 해봐도

암호화된 패스워드는 들어가지 않는데

임의로 작성한 패스워드는 DB에 잘 저장되는 사태가 나타났다ㅠㅠ

 

에러코드)

info : org.springframework.beans.factory.xml.xmlbeandefinitionreader - loading xml bean definitions from class path resource [org/springframework/jdbc/support/sql-error-codes.xml]

 

 

sql문에서 뭔가 문제가 있는 것으로 보여서

mapper에 있는 sql문을 직접 MySQL에 입력하고

내가 암호화했던 비밀번호를 복붙했더니 역시 삽입이 안 되는 것이다ㅠㅠ

 

그런데, 보다보니 암호화된 비밀번호가 너무 길었다...

생각해보니 pwd의 varchar(50) 밖에 안 된다는 걸 깨달았고

pwd의 varchar 용량(?)을 늘려주자 잘 작동하는 것을 확인했다 ^0^/

 

암호화 성공!

 

 

그러면 이제 복호화 도전!!!

 

 

 

LoginController

    @ResponseBody
    @PostMapping("/login")
    public String login(@RequestBody MemberDto dto, HttpServletRequest request) {
        // dto 잘 들어왔는지 확인
        System.out.println("dto = " + dto);
        // dto 널체크
        if(dto!=null) {
            try{
                MemberDto memberDto = service.login(dto);
                System.out.println("memberDtoPwd = " + memberDto.getPwd());
                // memberDto 널체크
                if(memberDto!=null) {
                    String id1 = dto.getId();
                    String id2 = memberDto.getId();
                    System.out.println("BEFORE matches");
                    boolean a = passwordEncoder.matches(dto.getPwd(), memberDto.getPwd());
                    System.out.println("a = " + a);

                    // 두 객체의 id, pwd 값이 같다면 로그인 성공
                    if(id1.equals(id2) && passwordEncoder.matches(dto.getPwd(), memberDto.getPwd())) {
                        HttpSession session = request.getSession();
                        session.setAttribute("id", id1);
                        return "LOGIN OK";
                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return "ID OR PWD CHECK PLZ";
    }

 

분명히 비밀번호를 제대로 쳤는데도

passwordEncoder.matches() 가 nullpointerException이 뜬다

왜일까...?

일단 login SQL문은 특수문자를 사용할 수 있게 수정했고...

 

 

 

이유를 알았다!

1) 입력받은 dto의 id를 이용해서 유저 정보를 select 한 다음

2) DB에 들어가있는 pwd와 입력한 pwd를 비교해야하는데

 

자꾸 입력한 id와 pwd로 DB에 정보를 불러내려고 하니 안됐던 것 ㅠ.ㅠ

입력한 pwd와 맞는 DB 정보는 없기 때문이다 ㅠㅠ(암호화 전 pwd기 때문)

 

 

 

그럼 컨트롤러를 수정하자!

 

LoginController

    @ResponseBody
    @PostMapping("/login")
    public String login(@RequestBody MemberDto dto, HttpServletRequest request) {
        // dto 잘 들어왔는지 확인
        System.out.println("dto = " + dto);
        // dto 널체크
        if(dto!=null) {
            try{
                //id로 form을 가져옴
                MemberDto memberDto = service.form(dto.getId());
                // memberDto 널체크
                if(memberDto!=null) {
                    // 두 객체의 pwd 값이 같다면 로그인 성공
                    if(passwordEncoder.matches(dto.getPwd(), memberDto.getPwd())) {
                        HttpSession session = request.getSession();
                        session.setAttribute("id", dto.getId());
                        return "LOGIN OK";
                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return "ID OR PWD CHECK PLZ";
    }

 

 

결과는?

 

 

DB에 암호화 된 pwd

하지만 유저가 회원 가입할 때 만든 pwd를 입력하면?

 

 

무사히 로그인 완료 :)

 

 

 

다음엔 무슨 기능을 구현해볼까?룰루랄라

728x90