Servlet을 사용할 땐 SHA-512 방식의 암호화를 사용해 보았는데 이번엔


BCrypt 방식을 이용해보자.


예제는 회원가입 시 Controller에서 입력받은 암호를 암호화 처리를 통해 변경하는 작업



MemberController.java


@Controller
public class MemberController {
    // 의존성 주입용 필드 선언
    // 어노테이션 + Interface 타입
    @Autowired
    private MemberService ms;
    // 인터페이스를 상속받는 객체에 @Component나 @Service 어노테이션이 필요
    // 객체 생성 시 new Service와 같은 부분을 Spring에게 맡기는것.
   
    @Autowired
    private BCryptPasswordEncoder passwordEncoder;


    @RequestMapping("insert.me")
    public String insertMember(Member m, Model model) {
       
        System.out.println("member : " + m);
       
        String encPassword = passwordEncoder.encode(m.getUserPwd());
       
        System.out.println(encPassword);
       
        m.setUserPwd(encPassword);
       
        int result = ms.insertMember(m);
       
        if (result > 0) {
            return "redirect:goMain.me";
        } else {
            model.addAttribute("msg", "회원가입 실패!");
            return "common/errorPage";
        }
       
    }

}



먼저 bcrypt란?
DB에 비밀번호를 저장할 목적으로 설계된 알고리즘

단방향 해쉬 함수는 암호화된 메세지를 수학적인 연산을 통해 암호화 된 메세지인 다이제스트를 생성한다.


원본 메세지를 가지고 암호화된 메세지를 복호화 할 수 있는 것을 양방향이라고 하고


암호화된 메세지를 복호화 할 수 없는 것을 단방향이라고 한다.


다이제스트란 결과값들이라고 생각하면 된다.


단방향 해쉬 함수도 사용하면 안되는 이유


1. 단방향 해쉬함수는 많은 다이제스트가 확보되면 평문을 찾아낼 수 있다.


2. 비밀번호를 저장하기 위한 목적으로 설계된 알고리즘이 아닌,


검색을 위해 설계된 알고리즘이다.


그만큼 다이제스트의 생성이 매우 빨라 뚫리는데 시간이 짧다.


이를 해결하기 위해 슬링(salting)기법이 추가되었다.


원본 메세지에 문자열을 추가하여 동일한 길이의 다이제스트를 생성하는 것을 슬링이라 한다.

하지만 salt 값을 알아내면 나머지는 단방향 해쉬함수를 통한 다이제스트를 복호화 하는 것과 별 차이가 없다.


bcrypt 방식은 이러한 salt값을 랜덤하게 생성하여 암호화를 하는 방식이다.


추가적으로 다이제스트를 생성하는데 걸릴 시간을 결정할 수도 있다.


생성 시간에 오래 걸린다면 대량의 다이제스트 생성 역시 오래걸리게 된다.


1999년에 발표되어 현재까지 자주 사용되는 강력한 비밀번호 저장용 매커니즘이다.





설명은 이렇고 사용 자체는 라이브러리 등록, 선언


암호화 메소드 or 암호 일치하는지?에 대한 메소드 선언밖에 없는 간단한 방법이다.






작업 순서로는


메이븐 시큐리티 라이브러리 추가 - Autowired 추가 - security xml 추가 - web.xml에 추가된 xml들 추가이다.







메이븐 시큐리티 라이브러리 pom.xml에 추가한다. - https://qdgbjsdnb.tistory.com/237


Autowired 추가는 빨간글자로 표시해 두었다.



다음은 web.xml 파일 추가부분


/WEB-INF/config/spring-security.xml 추가


    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:root-context.xml
            /WEB-INF/config/spring-security.xml
        </param-value>
    </context-param>



/WEB-INF/config/spring-security.xml의 설정을 읽어오라고 명시하였으니


해당 경로에 파일을 생성한다.


<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
   



    <beans:bean id="bcryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"></beans:bean>
   



</beans:beans>






기존에 있는 기본 beans 선언 안에


<beans:bean id="bcryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"></beans:bean>


BCryptPasswordEncoder Bean 선언만 하면 끝난다.








메소드의 경우는 BCryptPasswordEncoder 로 선언된 객체를 통해


encode(String형)을 사용하면 String형이 암호화되고


matches(입력한 암호, DB에 저장된 암호)를 입력했을 땐 암호가 일치하는치 체크해준다.(true or false)





        String encPassword = passwordEncoder.encode(m.getUserPwd());



        if (!passwordEncoder.matches(m.getUserPwd(), encPassword)) {
            throw new LoginException("로그인 실패!");
        } else {
            loginUser = md.selectMember(sqlSession, m);
        }






+ Recent posts