티스토리 뷰





반응형

요즘과 같이 개인정보가 중요한 시대에 회원가입을 암호화를 하지않는 다면 엄청 큰일로 다뤄진다. 그래서 페이지의 기본중 하나라고 할 수 있는 암호화를 해볼 생각이다. 전체적인 로직은 간단하다. 패스워드정보를 Servlet을 통해 DB로 가기전 Filter로 가로채 암호화 작업을 진행 후 Servlet한테 다시 건내주고 그 데이터를 저장하거나 조회한다.


순서

1. Filter를 통해 중간에 날아가는 데이터를 캐치한다.

2. 캐치된 데이터중 password와 관련된 정보만 추출하여 암호화를 진행한다.


2-1. getParameter를 오버라이딩을 해서 할 것이다.

2-2. 추출된 key값 password는 암호화 알고리즘인 SHA512로 암호화를 진행.


2-2-1. 암호화는 만들어진 MessageDigest에서 getInstance로 SHA-512를 가져와 쓸 것이다.

2-2-2. 암호화 하기전에 입력된 값을 byte 단위로 쪼갠다.

2-2-3. 쪼개진 패스워드를 update함수에 매개변수로 넣어주고 암호화 진행 후 다시 String으로 변환 후 리턴한다.


1.Filter 생성하기

먼저 필터부분이다. 사용자의 입력값이 들어 있는 request를 받는다. 그리고 EncryptWrapper라는 클래스는 아래서 만들것인데 저기다 넣어줄 것이다.(실제 암호화가 진행되는 클래스) req를 넣은 새로운 객체인 encW를 만들어주고 암호화 메소드인 getParameter를 실행시켜준다. 이후 chain.doFilter로 다음 필터로 옮기거나 없다면, 원래 가려던 서블릿으로 이동한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package common.filter;
 
import java.io.IOException;
 
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
 
import common.encrypt.EncryptWrapper;
 
/**
 * Servlet Filter implementation class EncryptFilter
 */
@WebFilter(
        servletNames= {
        "MemberEnrollEndServlet",
        "MemberLoginServlet"
        })
public class EncryptFilter implements Filter {
 
    /**
     * Default constructor. 
     */
    public EncryptFilter() {
        // TODO Auto-generated constructor stub
    }
 
    /**
     * @see Filter#destroy()
     */
    public void destroy() {
        // TODO Auto-generated method stub
    }
 
    /**
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        
        HttpServletRequest req = (HttpServletRequest)request;
        EncryptWrapper encW = new EncryptWrapper(req);
        encW.getParameter("password");
        
        chain.doFilter(encW, response);
    }
 
    /**
     * @see Filter#init(FilterConfig)
     */
    public void init(FilterConfig fConfig) throws ServletException {
        // TODO Auto-generated method stub
    }
 
}
cs


2.암호화하기

다음은 암호화가 이뤄지는 EncryptWrapper 클래스이다.

위의 필터는 그냥 other new에서 Filter를 지정하면 되지만 wrapper는 추가해줘야하는 부분이 있다.

 아래 사진으로 첨부하겠다.

 

 



저렇게 설정해주고 getParameter를 오버라이딩 처리 해주면 될 것.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package common.encrypt;
 
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.util.Base64;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
 
public class EncryptWrapper extends HttpServletRequestWrapper {
 
    public EncryptWrapper(HttpServletRequest request) {
        super(request);
        // TODO Auto-generated constructor stub
    }
    
    @Override
    public String getParameter(String key) {
        String value="";
        if(key!=null && key.equals("password")) {
            value = super.getParameter("password");
            value = getSha512(value);
        }
        else {
            //password가 아닌 값들은 특정한 처리를 하지않고 그냥 value에 넣는다.
            value = super.getParameter(key);
        }
        return value;
    }
    
    public static String getSha512(String password) {
        String encPwd ="";
        
        //sha512방식의 암호화 객체 생성, 암호화 하는 객체
        MessageDigest md =null;
        try {
            md = MessageDigest.getInstance("SHA-512");
        }catch (Exception e) {
            e.printStackTrace();
        }
        
        //암호화 하기전 패스워드를 바이트 단위로 먼저 쪼개주는 작업
        byte[] bytes = password.getBytes(Charset.forName("UTF-8"));
        //쪼개진 패스워드를 md의 update로 암호화 작업 진행
        md.update(bytes);
        //다시 String형으로 바꾸는 작업
        encPwd = Base64.getEncoder().encodeToString(md.digest());
        return encPwd;
    }
 
}
cs


key값으로 password가 들어올 때만 처리하도록 로직을 위와 같이 짜면 되며 아래의 로직은 위에서 설명과 같다. md에 암호화 객체를 받아 getInstance로 SHA512를 가져오고 패스워드를 암호화가 가능한 형태인 바이트단위로 쪼개준다음 md.update로 돌린 후 return하는 로직이다. 그리고 이제 중요한 부분이 매핑인데 아래는 처음 사진의 19번째 줄에 있던 매핑값이다. 서블릿네임은 저렇게 적어 놓은 서블릿으로 가는값들이 있으면 그 서블릿으로 가기전에 필터가 먼저 한번 가로챈다는 의미다. 즉 회원가입과 로그인으로 가는 요청이 있다면 가로 챈다고 생각하면 될 것같다.

@WebFilter(
        servletNames= {
        "MemberEnrollEndServlet",
        "MemberLoginServlet"
        })


하지만 이 매핑정보는 Filter만 하는것이 아니라 Servlet에서도 해줘야한다. 

다음은 MemberLoginServlet의 대한 매핑정보다.

@WebServlet(urlPatterns="/login.do",name="MemberLoginServlet" )


필터와 서블릿은 name으로 맞춰주기만 하면되는것이고 urlPatterns는 jsp 파일이 요청할때 사용되는 정보다. 이렇게 하면 서블릿에 도착하기전에 암호화가 되어있는 패스워드를 볼 수 있다. 주의할점은 이미 회원정보가 암호화 하지 않은 상태로 들어가 있는데 암호화를 한 값을 보내면 에러가 날테니 그런 정보가 있다면 DB로 직접 들어가 update구문을 해줘야 할 것이다. commit도 잊지말고 하길 바란다.


결과 확인


반응형
댓글
반응형
최근에 달린 댓글
글 보관함
Total
Today
Yesterday
최근에 올라온 글
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30