Coding Planet
[Servlet] 암호화 필터 예제 본문
반응형
1. 암호화 필터(EncryptFilter)
(필터에 대한 설명은 이전 포스트 참고: https://sharonprogress.tistory.com/150)
- 로그인을 기능을 구현하기 위해서는 이메일, 비밀번호가 일치하는 회원을 조회하는 과정이 필요하다. 이때 개인정보에 해당하는 비밀번호의 경우 개인정보보호법에 의해 암호화를 해야하는데, 이를 위해 암호화 필터가 필요하다.
- 암호화 필터는 보안이 필요한 로그인, 회원가입, 비밀번호 변경, 회원 탈퇴등에 쓰이는 필터로 인코딩 필터와는 달리 선택적으로 사용되므로 url을 String[]로 설정해야한다.
- 다만, 이 필터에서는 비밀번호 값을 재 세팅하는 것이 불가능해 Wrapper Class를 사용해 오버라이딩을 하고 그 값을 반환 받아야 한다.
package edu.kh.community.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.HttpFilter;
import javax.servlet.http.HttpServletRequest;
import edu.kh.community.common.wrapper.EncrpytWrapper;
//암호화를 적용해야하는 요청: 로그인, 회원가입, 비밀번호 변경, 회원 탈퇴
// urlPatterns에 적용될 url이 여러개인 경우: String 배열 초기화 형태인 {}로 작성
@WebFilter(filterName="encrpytFilter",
urlPatterns={"/member/login",
"/member/signUp",
"/member/myPage/changePw",
"/member/myPage/secession"})
public class EncrpytFilter extends HttpFilter implements Filter {
public void init(FilterConfig fConfig) throws ServletException { }
public void destroy() { }
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//HttpServletRequest에 비밀번호 담겨 있음
//부모타입에 맞추기 위해 다운캐스팅 필요
HttpServletRequest req =(HttpServletRequest)request;
//파라미터를 다시 세팅하는 방법은 필터에서는 불가능!
//Servlet의 Wrapper 클래스를 이용해소 HttpServletRequest의 메서드를 오버라이딩
//-> 오버라이딩을 통해 비밀번호 암호화 진행
EncrpytWrapper wrapper = new EncrpytWrapper(req);
chain.doFilter(wrapper, response);
}
}
2. EncryptWrapper 클래스
- EncrpytWrapper를 호출한 filter로부터 HttpServletRequest 객체를 매개변수로 전달받는다.
- 비밀번호를 암호화 하여 다시 세팅하기 위해 getParameter()를 오버라이딩 한다. 이때 getParameter()의 매개변수 String name은 사용자로부터 입력받안 태그의 name값이다.
- 매개변수로 전달받은 값을 암호와 메서드로 세팅해 암호화된 값을 반환한다(value)
- SHA-512 해시 함수는 어떤 문자열이든 일정한 길이의 무작위 문자열로 반환하는 암호화 함수이다.
- 해당 메서드 내에서 단방향 해시 함수 값을 구할 때 사용하는 MessageDigest 클래스를 통해 암호화를 한다.
- 이 때 MessageDigest는 호출, 리턴을 byte[]로 받기 때문에 String으로 변환하는 과정이 필요하다.
- base64는 임의의 바이트 스트림을 화면에 표시할 수 있는 ASCII 문자들로 바꾸는 인코딩 방식을 의미한다.
- 결국 SHA-512 해시 함수가 반환한 바이트 형식을 문자열로 전환하는 것이다.
(MessgaeDigest 클래스는 이 포스트를 참고! : https://sharonprogress.tistory.com/151)
package edu.kh.community.common.wrapper;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class EncrpytWrapper extends HttpServletRequestWrapper {
//HttpServletRequestWrapper
// - 클라이언트 요청 객체 HttpServletRequest를 오버라이딩 하는 방법을 제공하는 클래스
//생성자가 작성되어 있으면
//컴파일러가 기본 생성자 자동으로 추가 안해줌
//->Wrapper 클래스 생성 시 반드시 HttpServletRequest 객체를 매개변수로 전달해야 한다.
public EncrpytWrapper(HttpServletRequest request) {
super(request);
}
//getParameter() 오버라이딩
@Override
public String getParameter(String name) {
//매개변수 name : input 태그의 name 속성 값
//return super.getParameter(name): 기존 getParameter()메서드
String value = null;
switch(name) {
case "inputPw":
case "memberPw" :
case "currentPw" :
case "newPw":
value = getSha512(super.getParameter(name));
break;
//dafault: 암호화가 필요 없는 경우에는 기존 getParameter()메서드 형태를 유지
default : value = super.getParameter(name);
}
return value;
}
//암호화 메서드(SHA-512 해시 함수)
//해시 함수 : 어떤 문자열이든 일정한 길이의 무작위 문자열로 변환하는 함수(중복 X)
private String getSha512(String pw) {
//매개변수 pw : 암호화되기 이전의 비밀번호, 입력값
//암호화된 비밀번호 저장 변수
String encryptPw = null;
//1. 해시 함수를 수행할 객체를 참조 변수 선언
MessageDigest md = null;
try {
//2. SHA-512 방식의 해시 함수를 수행할 수 있는 객체를 얻어옴
md = MessageDigest.getInstance("SHA-512");
//3. md를 이용해 암호화를 진행할 수 있도록 pw를 byte[] 형태로 변환
byte[] bytes = pw.getBytes(Charset.forName("UTF-8"));
//4. 암호화 수행 -> 암호화 결과가 md 내부에 저장
md.update(bytes);
//5. 암호화된 비밀번호를 encryptPw에 대입
// -> byte[]를 String 변환해야함
// -> Base64: byte 코드를 무자열로 변화하는 객체
encryptPw = Base64.getEncoder().encodeToString(md.digest());
System.out.println("암호화 전: " + pw);
System.out.println("암호화 후: " + encryptPw);
}catch(NoSuchAlgorithmException e) {
e.printStackTrace();
}
return encryptPw;
}
} //end of class
반응형
'Server' 카테고리의 다른 글
[JDBC] Oracle DB 연동 JDBC : SELECT 예제 (0) | 2023.04.04 |
---|---|
[JDBC] executeQuery와 executeUpdate()의 차이는?, 실제 사용 예제 포함 (0) | 2023.04.02 |
[JDBC] MVC 패턴으로 JDBC 구현하기 (0) | 2023.03.23 |
[Servlet/JSP] 내장 객체와 범위(scope), 내장 객체의 우선순위 (0) | 2023.03.21 |
[JSP] JSP(Java Server Page)란? Servlet와 JSP의 차이점, 지시어, 스크립팅 원소 (0) | 2023.03.20 |
Comments