본문 바로가기

Web

security 모든 형태 구조 + properties 활용

● 암호화 - bit 단위로 문자를 별도의 임의 값으로 변경을 하는 것을 말함

MD5(128bit) : 해시 암호화 코드(default/가장 많이 쓰는 형태) ex) 쇼핑몰
SHA-1(160bit) : MD5에서 보다 높은 bit를 활용하여 사용하는 방식 -내부시스템
SHA-2(128,224,256,384,512bit) : SHA-1에서 개발자가 직접 bit를 선정하도록 update -> AI 에 뚫림
SHA-3(256,384,512bit) : SHA2에서 특수문자 형태의 코드를 추가 
RSA (2048bit) : 전자서명을 사용하는 형태로 암호화 (Linux에서 최초 개발) 금융관련 = md5 + RSA

 

● MD5

암호화 라이브러리 => try~catch 사용
		try {
			//암호화 라이브러리
			MessageDigest md5 = MessageDigest.getInstance("MD5");
            //암호화는 bit단위로 이루어지기 때문에 getBytes()로 변환
			md5.update(mpass.getBytes()); 
			byte[] m = md5.digest();
			//System.out.println(m);
			StringBuilder sb = new StringBuilder();
			for(byte w : m) {
				// % :문자 포맷 - %x(소문자+숫자) %X(대문자+숫자) : 16진수 형태의 구성
				//문자 포맷(2진수) : %02x
				//문자 포맷(8진수) : %08x
				String word = String.format("%08x", w);
				sb.append(word);
			}
			System.out.println(sb);		
		} catch (Exception e) {
			e.printStackTrace();
			//무조건 string으로 받아야함 (int,long등으로 못받음)
			System.out.println("올바른 문자가 아니어서 암호화가 정상 작동되지 않습니다.");
		}
	}
}​
① 의 출력 결과
 ① 받아온 데이터인 mpass 를 md5로 암호화 하기 위해 get.byte로 bit로 변환 후 md5형태로 암호화 함




② 변환된 'm' 값을 string.format을 이용해 문자포맷
%x 로 돌림

 

%X 로 돌림

③ 진행 시 주르륵 나오므로 문자열로 받기 위해 StringBuilder 로 문자열로 변환
       (2진수, 8진수 등으로도 변환 가능)
그냥 %x(16진수)로 돌려 문자열로 출력한 결과
   e1adc3949ba59abbe56e057f2f883e(16진수)
   e10adc3949ba59abbe56e057f20f883e(2진수)         000000e10000000a000000dc0000003900000049000000ba00000059000000ab000000be00000056000000e000000057 000000f20000000f000000880000003e(8진수)

 

● SHA - 1, SHA - 2, SHA - 3

MD5형태에서 MessageDigest.getInstance("SHA1");부분만 수정해주면 됨
        MessageDigest md5 = MessageDigest.getInstance("SHA-256"); : 	//SHA-2 쓰는 형태
        MessageDigest md5 = MessageDigest.getInstance("SHA3-224");		//SHA-3​

- 출력 결과 예시 ('123456'을 변환)
e1adc3949ba59abbe56e057f2f883e(16진수) -MD5 기본 7c4a8d9ca3762af61e59520943dc26494f8941b - SHA1 f8cdb04495ded47615258f9dc6a3f4707fd2405434fefc3cbf4ef4e6 - SHA2형태
8d969eef6ecad3c29a3a629280e686cfc3f5d5a86aff3ca122c923adc6c92 6be790258b73da944199c4cb6aeec1fc883152dd74e7581b70a648 -SHA3형태

 

 

● DB에 저장시킨 암호화된 값을 입력받은 값과 비교 

● 로그인 시 db에 암호화 된 형태로 저장된 패스워드와 비교 (아래 코드에서는 DB에서 불러오지 않고 직접 입력함)
   
   1.비교 시 자료형 맞춰줘야함
   2.비교하는 코드 예시
	protected void doPost(HttpServletRequest request, HttpServletResponse response) 
    			hrows ServletException, IOException {
		String mpass = request.getParameter("mpass"); //사용자가 입력한 값
		String db = "e1adc3949ba59abbe56e057f2f883e"; //DB에 저장된 값
		
		try {
			//암호화 라이브러리
			MessageDigest md5 = MessageDigest.getInstance("MD5");
			md5.update(mpass.getBytes()); 
			byte[] m = md5.digest();
			StringBuilder sb = new StringBuilder();
			for(byte w : m) {
				String word = String.format("%x", w);
				sb.append(word);
			}
			System.out.println(sb);	
			//암호화로 생성된 객체 자료형은 stringbuild 이므로 
            //string으로 형 변환 후 비교해야 정상적으로 핸들링가능
			//sb는 stringbuilder 이고 db 는 string이므로 자료형 맞춰야함
            if(sb.toString().equals(db)) {
				System.out.println("로그인 하셨습니다.");
			}else {
				System.out.println("패스워드를 확인하세요");
			}
		} catch (Exception e) {
			e.printStackTrace();
			//무조건 string으로 받아야함 (int,long등으로 못받음)
			System.out.println("올바른 문자가 아니어서 암호화가 정상 작동되지 않습니다.");
		}
	}
}​


 

 

● 암호화된 password를 저장시키기 위한 DB table 설계

패스워드 컬럼 크기 설정
' md5 '
 : 80~100(16진수) =>md5  (2진수,5진수) : 150~200
' sha '
 :  text 로 설정

설계 예시)
create table login(
midx int(8) not null auto_increment,
mid varchar(30) not null,
mpass varchar(80) not null,
primary key(midx),
unique key(mid)
);

 

 

 

● properties 활용

● properties 파일 생성

- properties 는 해당 로드값을 메모리에 저장시킨 후 프로세서가 종료되면 자동으로 소멸
 => closing할 필요가 없음

1. WEB-INF 에 classes 폴더생성 (외부로부터의 db접근을 제한하기 위함 : web_inf는 외부접근을 차단)
2. classes 폴더에 db.properties '파일'생성 
① properties 를 직접 만들어 놓고 로드하기


db.properties 파일 내용

② do에서 바로 생성

	Properties pp = new Properties();
		pp.put(앞단, 뒷단);
		pp.put(앞단, 뒷단);
		pp.put(앞단, 뒷단);

 

● properties 파일 활용해서 db 연결

1.  java로 ' dbcon ' 이라는 class 생성 후 라이브러리로 classes에 있는 properties 파일을 사용

코드 예시)  database 연결 + properties 활용
	public class dbcon { 
	//classes 에 있는 properties 파일을 사용하는 라이브러리 
		Properties pp = new Properties(); 
   	 	String resource = "db.properties"; //로드 할 properties 파일 명 
    	public Connection db() throws Exception{ 
        	//classes 안에 있는 properties 를 로드하여 모든 문자 내용을 저장시킴 
    		this.pp.load(this.getClass().getClassLoader().getResourceAsStream(resource)); 
        	Class.forName(this.pp.getProperty("driver")); 
        	Connection con = DriverManager.getConnection(this.pp.getProperty("url"),this.pp.getProperty("user"),this.pp.getProperty("password")); 
        		return con; 
		} 
	}​​


 - properties 파일 안의 내용도 찍어볼 수 있음

System.out.println(this.pp.getProperty("user")); 이용
getProperty("properties파일 안의 내용")을 이용해서 다 로드 가능함
properties 파일에 sql(ddl) 구문 넣고 사용가능함 - ddl은 module 에 들어가야함 (controll에 넣으면 안됨)

코드)  properties 파일의 user 값을 가져옴

	public class dbcon { 
		//classes 에 있는 properties 파일을 사용하는 라이브러리 
		Properties pp = new Properties(); 
    	String resource = "db.properties"; //로드 할 properties 파일 명 
    	public Connection db() throws Exception{ 
    		//classes 안에 있는 properties 를 로드하여 모든 문자 내용을 저장시킴 
        	this.pp.load(this.getClass().getClassLoader().getResourceAsStream(resource)); 
        	System.out.println(this.pp.getProperty("user")); 
        	Class.forName(null); 
       	 	Connection con = DriverManager.getConnection(null); 
        	return con; 
   	 	}
 	}​

하고 loginok2.do 생성 후  db connection 만 해주고 실행하면 

	@WebServlet("/loginok2.do") 
	public class login extends HttpServlet { 
		private static final long serialVersionUID = 1L; 
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) 
    			throws ServletException, IOException { 
            	dbcon dc = new dbcon(); 
            	try { 
           	 	Connection con = dc.db(); 
            	} catch (Exception e) { 
           	 	System.out.println("DB 연결 실패!!"); 
			} 
    	} 
 	}	​

properties 파일의 user 인 hana가 찍히는 것을 확인

 

 

● MVC형태로 문자를 md5 로 변환하는 Class 생성

사용자가 입력한 패스워드를 md5로 변환 후 return 하는 메소드를 생성
    public class passwd_md {
        private StringBuilder repass = new StringBuilder();
        private String ori_pass = null;
        private MessageDigest md5 = null;

        public passwd_md(String userpw) { //pw를 받아오는 파트
            this.ori_pass = userpw;
        }
        //사용자가 입력한 패스워드를 md5로 변환 후 return 하는 메소드
        public String md5_passwd() {
            try {
                this.md5= MessageDigest.getInstance("md5");
                this.md5.update(this.ori_pass.getBytes());
                byte[] md = md5.digest();

                for(byte ck : md) {
                    String m = String.format("%x", ck);
                    this.repass.append(m);
                }
            } catch (Exception e) {
                System.out.println("앙호화 변환 오류");
            }
            //리턴할 메소드 자료형이 string으로 toString을 이용함
            return this.repass.toString();
        }
    }​

 

properties 에 ddl 구문 넣고 사용시 주의
     - properties 를 쓰면 preparedstatement만 사용가능함
       다른건 사용하지 못함 (ddl구문안에 다른 변수 활용x)
driver = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://localhost:3306/cms
user = hana
password = hana1234
select_db = select * from login where mid=? order by midx desc​
    @WebServlet("/loginok2.do")
    public class login extends HttpServlet {
        private static final long serialVersionUID = 1L;
        Properties pp = new Properties();
        String ddl = "db.properties"; //ddl 구문 작성한 장소
        PreparedStatement ps = null;
        ResultSet rs = null;

        protected void doPost(HttpServletRequest request, HttpServletResponse response) 
                        throws ServletException, IOException {
            String mid = request.getParameter("mid");
            String mpass = request.getParameter("mpass");

            dbcon dc = new dbcon();
            try {
                Connection con = dc.db();		

                this.pp.load(this.getClass().getClassLoader().getResourceAsStream(ddl));
                this.ps = con.prepareStatement(this.pp.getProperty("select_db"));
                this.ps.setString(1, mid);
                this.rs = this.ps.executeQuery();
                this.rs.next();
                String db_mid = this.rs.getString("mid");
                String db_mpass = this.rs.getString("mpass");

                String userpw = new passwd_md(mpass).md5_passwd();

                if(userpw.equals(db_mpass)) {
                    System.out.println("로그인 하셨습니다.");
                }else {
                    System.out.println("올바른 패스워드가 아닙니다.");
                }		
                this.rs.close();
                this.ps.close();
                con.close();
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("DB 연결 실패!!");
            }
        }
    }

 

'Web' 카테고리의 다른 글

SMTP - IMAP/SMTP (메일서버)사용해서 메일 발송  (0) 2024.07.05
[jsp] jsp 에서 split 사용  (0) 2024.07.05
로그인 / 로그아웃  (0) 2024.07.03