'DEVELOPER/lang'에 해당되는 글 18건
- 2014.07.10 XMLWriter
- 2013.07.18 Apache + mod_wsgi + Flask
- 2013.07.15 wxPython 설치
- 2013.07.09 Flask 어플리케이션 테스트하기
- 2013.06.26 대칭 암호화/복호화 ― 간단한 예제에서 DB 적용까지
- 2013.06.26 CodeIgniter .htaccess 설정 예제
- 2013.06.26 CodeIgniter - MSSQL 사용하기 1
- 2013.06.26 Complie 중 error: stray '\357' in program 해결
아파치는 설치되어 있다 가정하고...
1. Flask app editing
2. mod_wsgi install
3. httpd.conf editing
4. Apache restart
1. Flask app editing
$ cd /[app path]
$ vim [app name].wsgi
# 아래 추가.
import sys
sys.path.insert(0, "/[app path]")
from [app name] import app as application
2. mod_wsgi install
$ cd /usr/local/src
$ sudo weget http://modwsgi.googlecode.com/files/mod_wsgi-3.4.tar.gz
$ sudo tar zxvf mod_wsgi-3.4.tar.gz
$ cd mod_wsgi-3.4
$ sudo ./configure --with-apxs=/usr/local/apache/bin/apxs --with-python=/usr/local/bin/python (경로는 알아서...)
$ sudo make
$ sudo make install
3. httpd.conf editing
$ cd /usr/local/apache/conf
$ sudo vim httpd.conf
# 아래 추가.
LoadModule wsgi_module modules/mod_wsgi.so
AddHandler wsgi-script .wsgi
$ sudo vim extra/httpd-vhosts.conf
# 아래 추가.
<VirtualHost *:80>
ServerName [도메인]
ServerAdmin [관리자이메일]
WSGIDaemonProcess [app name] user=nobody group=nobody threads=5
WSGIScriptAlias / /[app path]/[app name].wsgi
#WSGIRestrictStdout Off
<Directory /[app path] >
WSGIProcessGroup [app name]
WSGIApplicationGroup %{GLOBAL}
WSGIScriptReloading On
#Options Includes ExecCGI
#AllowOverride None
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
4. Apache restart
난 앱등이니까 Mac
1. 쉬운방법
- brew 사용
- brew install wxwidgets (Cross-Platform GUI Library)
32bit 로 돌리기 위한거 같다.
defaults write com.apple.versioner.python Prefer-32-Bit -bool yes
Something that is untested is broken.
이 문구의 기원을 정확하게 알수는 없지만, 이것은 진실에 가깝다. 테스트되지 않은 어플리케이션은들은 기존 코드의 개선을 어렵게 하며 프로그램 개발자들을 심한 편집증환자로 만들어 버린다. 만약 어플리케이션의 테스트들이 자동화 되어 있다면, 우리는 문제가 발생했을때 안전하며 즉각적으로 변경이 가능하다.
Flask는 Werkzeug 를 통해 테스트 Client 를 제공하여 어플리케이션의 컨텍스트 로컬을 처리하고 테스트할 수 있는 방법을 제공한다. 그리고 당신이 가장 좋아하는 테스팅 도구를 사용 할 수 있도록 해준다. 이 문서에서 우리는 Python에서 기본으로 제공하는 unittest 를 사용 할 것이다.
어플리케이션
첫째로 우리는 테스트할 어플리케이션이 필요하다. 우리는 튜토리얼 에서 소개된 어플리케이션을 사용할 것이다. 아직 어플리케이션이 준비되지 않았다면 the examples 에서 소스코드를 준비하자.
테스팅 스켈레톤(Skeleton)
어플리케이션을 테스트 하기 위해서, 우리는 두번째 모듈 (flaskr_tests.py) 을 추가하고 단위테스트 스켈레톤(Skeleton)을 만든다.:
setUp() 함수의 코드는 새로운 테스트 클라이어트를 생성하고 새로운 데이터베이스를 초기화 한다. 이 함수는 각각의 테스트 함수가 실행되기 전에 먼저 호출된다. 테스트후 데이터베이스를 삭제하기 위해 tearDown() 함수에서 파일을 닫고 파일시스템에서 제거 할 수 있다. 또한 setup 함수가 실행되는 동안에 TESTING 플래그(flag)가 활성화된다. 요청을 처리하는 동안에 오류 잡기(error catch)가 비활성화되어 있는 것은 어플리케이션에대한 성능테스트에 대하여 좀 더 나은 오류 리포트를 얻기 위해서이다.
이 테스트 클라이언트는 어플리케이션에대한 단순한 인터페이스를 제공한다. 우리는 어플리케이션에게 테스트 요청을 실행시킬 수 있고, 테스트 클라이언트는 이를 위해 쿠키를 놓치지 않고 기록한다.
SQLite3는 파일시스템 기반이기 때문에 임시 데이터베이스를 생성할때 tempfile 모듈을 사용하여 초기화 할 수 있다. mkstemp() 함수는 두가지 작업을 수행한다: 이 함수는 로우-레벨 파일핸들과 임의의 파일이름을 리턴한다. 여기서 임의의 파일이름을 데이터베이스 이름으로 사용한다. 우리는 단지 db_fd 라는 파일핸들을 os.close() 함수를 사용하여 파일을 닫기전까지 유지하면 된다.
만약 지금 테스트 실행한다면, 다음과 같은 출력내용을 볼 수 있을 것이다.:
비록 실제 테스트를 실행하지는 않았지만, 우리는 이미 flaskr 어플리케이션의 문법구문상으로 유효하다는 것을 벌써 알게되었다, 그렇지 않다면 어플리케이션이 종료되는 예외상황을 겪었을 것이다.
첫번째 테스트
이제 어플리케이션의의 기능 테스트를 시작할 시간이다. 어플리케이션의 루트 (/)로 접근하였을때 어플리케이션이 “No entries here so far” 를 보여주는지 확인해야 한다. 이 작업을 수행하기 위해서, 우리는 새로운 테스트 메소드를 다음과 같이 클래스에 추가하여야 한다.:
우리의 테스트 함수들의 이름이 test 로 시작하고 있다는 것에 주목하자. 이점을 활용하여 unittest 에서 테스트를 수행할 함수를 자동적으로 식별할 수 있다.
self.app.get 를 사용함으로써 HTTP GET 요청을 주어진 경로에 보낼 수 있다. 리턴값은 response_class 객체의 값이 될 것이다. 이제 data 의 속성을 사용하여 어플리케이션 으로부터 넘어온 리턴 값(문자열)을 검사 할 수 있다. 이런 경우, 'No entries here so far' 가 출력 메시지에 포함되어 있는 것을 확인해야 한다.
다시 실행해 보면 하나의 테스트에 통과 한 것을 확인할 수 있을 수 있을 것이다.
입력과 출력 로깅
우리의 어플리케이션에서 대부분의 기능은 관리자만 사용이 가능하다. 그래서 우리의 테스트 클라이언트에서는 어플리케이션의 입력과 출력에대한 로그를 기록할 수 있어야 한다. 이 작업을 작동시키려면, 로그인과 로그아웃 페이지요청들에 폼 데이터(사용자이름과 암호) 를 적용해야 한다. 그리고 로그인과 로그아웃 페이지들은 리다이렉트(Redirect)되기 때문에 클라이언트에게 follow_redirects 를 설정해 주어야 한다.
다음의 두 함수를 FlaskrTestCase 클래스에 추가 하자
이제 로그인과 로그아웃에 대해서 잘 작동하는지, 유효하지 않은 자격증명에 대해서 실패 하는지 쉽게 테스트 하고 로깅 할 수 있다. 다음의 새로운 테스트를 클래스에 추가 하자:
메시지 추가 테스트
메시지를 추가 하게 되면 잘 작동하는지 확인해야만 한다. 새로운 테스트 함수를 다음과 같이 추가 하자
여기에서 우리가 의도한 대로 제목을 제외한 부분에서 HTML이 사용가능한지 확인한다.
이제 실행 하면 세가지 테스트를 통과 할 것이다.:
헤더값들과 상태코드들이 포함된 보다 복잡한 테스트를 위해서는, MiniTwit Example 예제 소스의 좀 더 큰 어플리케이션의 테스트 수헹방법을 확인하자.
다른 테스팅 기법들
위에서 살펴본 대로 테스트 클라이언트를 사용하는 것 이외에, test_request_context() 함수를 with 구문과 조합하여 요청 컨텍스트를 임시적으로 할성화 하기 위해 사용 될 수 있다. 이것을 이용하여 request , g 과 session 같은 뷰 함수들에서 사용하는 객체들에 접근 할 수 있다. 다음 예제는 이런 방법들을 보여주는 전체 예제이다.:
컨텍스트와 함께 바인드된 모든 객체는 같은 방법으로 사용이 가능하다.
만약 서로 다른 설정구성으로 어플리케이션을 테스트하기 원할경우 이것을 해결하기 위한 좋은 방법은 없는것 같다. 이와 같이 어플리케이션을 테스트 하려면 어플리케이션 팩토리에 대해서 고혀해 보길 바란다. (참고 어플리케이션 팩토리)
그러나 만약 테스트 요청 컨텍스트를 사용하는 경우 before_request() 함수 와 after_request() 는 자동으로 호출되지 않는다. 반면에:meth:~flask.Flask.teardown_request 함수는 with 블럭에서 요청 컨텍스트를 빠져나올때 실제로 실행된다. 만약 before_request() 함수도 마찬가지로 호출되기를 원한다면, preprocess_request() 를 직접 호출해야 한다.:
이경우 어플리케이션이 어떻게 설계되었느냐에 따라 데이터베이스 컨넥션 연결이 필요할 수도 있다.
만약 after_request() 함수를 호출하려 한다면, process_response() 함수에 응답객체(Response Object)를 전달하여 직접 호출하여야 한다:
이같은 방식은 일반적으로 해당 시점에 직접 테스트 클라이언트를 사용 할 수 있기 때문에 크게 유용한 방법은 아니다.
컨텍스트 유지시키기
New in version 0.4.
때로는 일반적인 요청이 실행되는 경우에도 테스트 검증이 필요해질 경우가 있기 때문에 컨텍스트 정보를 좀더 유지 하는 것이 도움이 될 수 있다. Flask 0.4 버전에서 부터는 test_client() 를 with 블럭과 함께 사용하면 가능하다.:
만약 test_client() 를 with 블럭이 없이 사용한다면 , request 가 더이상 유효하지 않기 때문에 assert 가 실패 하게 된다. (그 이유는 실제 요청의 바깥에서 사용하려고 했기 때문이다.)
세션에 접근하고 수정하기
New in version 0.8.
때로는 테스트 클라이언트에서 세션에 접근하고 수정하는 일은 매우 유용할 수 있다. 일반적으로 이를 위한 두가지 방법이 있다. 만약 세션이 특정 키 값으로 설정이 되어 있고 그 값이 컨텍스트를 통해서 유지 된다고 접근 가능한것을 보장하는 경우 flask.session:
그렇지만 이와 같은 경우는 세션을 수정하거나 접급하는 하는 것을 요청이 실행되기전에 가능하도록 해주지는 않는다. Flask 0.8 버전 부터는 “세션 트랜잭션(session transparent)” 이라고 부르는 세션에 대한 적절한 호출과 테스트 클라이언트에서의 수정이 가능한지 시뮬레이션이 가능하도록 하고 있다. 트랜잭션의 끝에서 해당 세션은 저장된다. 이것은 백엔드(backend)에서 사용되었던 세션과 독립적으로 작동가능하다.:
이경우에 flask.session 프록시의 sess 객체를 대신에 사용하여야 함을 주의하자. 이 객체는 동일한 인터페이스를 제공한다.
암호화에 대한 기본 상식
암호화(Encryption)의 방식에는 단방향 암호화, 대칭 암호화, 비대칭 암호화가 있다.
단방향 암호화(One-way Encryption)는 복호화할 수 없도록 하는 방식이다. 이 방식에서는 해시 알고리즘(Hash Algorithm)을 사용하는데, 이 과정을 통해 고유한 지문(Fingerprint)을 생성한다.
일반적으로, 단방향 암호화를 통해 얻은 값으로는 복호화가 불가능하다고 하는데 원문이 짧거나 일반적으로 널리 사용되는 문자열일 경우에는 무작위 값 입력을 통한 공격(Brute Force Attack)을 통해 무력화되기 쉽다.
MD5, SHA1 등이 대표적인 해시 알고리즘이다.
대칭 암호화(Symmetric Encryption)는 키(Key)를 통해 동일한 알고리즘으로 암호화/복호화를 하는 방법이다. 이 방식은 2차 세계대전 중에 암호화 기계(Enigma Machine)에 사용된 방식이다.
암호화/복호화에 필요한 키가 유출되지만 않는다면 매우 안전한 방식이다. DES, TWOFISH, GOST 등이 대표적인 알고리즘이다.
비대칭 암호화(Asymmetric Encryption)는 SSL 같은 방식이라고 하는데, 자세한 내용은 모르므로 넘어가겠다.
이 글에서는 PHP에서 대칭 암호화 방식을 통한 암호화/복호화에 대해 설명하겠다.
MCRYPT 라이브러리의 설치와 설정
PHP에서는 Mcrypt 라이브러리를 통해 대칭 암호화를 지원한다. 따라서 Mcrypt를 이용하려면 라이브러리를 추가로 설치해 주어야 한다.
http://mcrypt.sourceforge.net/에서 Mcrypt 라이브러리를 다운로드 받을 수 있으며, 윈도우 서버라면 http://files.edin.dk/php/win32/mcrypt/에서 컴파일된 라이브러리 파일을 다운로드 받아 사용할 수 있다. 작동하도록 설정하려면 php.ini의 설정을 변경해 주어야 하는데, 자세한 설정 방법은http://www.php.net/manual/kr/book.mcrypt.php 에서 확인할 수 있다.
데비안 계열 리눅스 서버라면 터미널에서 다음의 명령어를 입력하는 것으로 Mcrypt를 설치와 설정을 완료할 수 있다.
1 | $ sudo apt-get install php5-mcrypt |
2 | $ sudo apt-get install libmcrypt4 |
3 | $ sudo /etc/init.d/apache2 restart |
MCRYPT를 이용한 암호화/복호화 예제
다음의 코드를 보면 쉽게 이해할 수 있다.
1 | $key = "열쇠" ; |
2 | $plainData = "개인정보" ; |
3 | $encryptedDataOnBinary = mcrypt_ecb(MCRYPT_GOST, $key , $plainData , MCRYPT_ENCRYPT); |
4 | $encryptedData = base64_encode ( $encryptedDataOnBinary ); |
5 | echo "암호화 할 평문 : " . $plainData ; |
6 | echo "<br/>" ; |
7 | echo "암호화 결과로 나온 바이너리 값: " . $encryptedDataOnBinary ; |
8 | echo "<br/>" ; |
9 | echo "암호화 결과를 아스키 코드로 변환한 값 : " . $encryptedData ; |
앞서 설명했듯, 대칭 암호화를 하기 위해서는 키가 필요하다. 이 예제에서는 $key로 “열쇠”라는 임의의 문자열을 넣었는데 실제로는 더 복잡하고 고유한 것을 사용하는 것이 좋겠다. $plainData는 암호화 할 대상을 말한다. 이 예제에서는 예로 “개인정보”라는 문자열을 넣어보았다.
mcrypt는 여러 기본 함수를 제공하는데, 그 중 이번에는 mcrypt_ecb() 함수를 이용했다. 참고로 ECB란 전자 부호표 모드(Electric CodeBook mode)의 약자다. mcrypt_ecb() 함수에는 네 가지 값을 넣어주어야 하는데, Mcrypt에서 제공하는 알고리즘 상수, 키, 암호화 할 값, 암호화/복호화를 위한 상수가 그것이다.
Mcrypt에서는 DES, TWOFISH, GOST 등 많은 알고리즘을 지원하는데 이 목록은http://www.php.net/manual/en/mcrypt.ciphers.php에서 확인할 수 있다. 이 예제에서는 GOST 방식을 사용하기 위해 MCRYPT_GOST라는 상수를 사용했다. 또한 이 예제에서는 암호화을 할 것이므로 MCRYPT_ENCRYPT라는 상수도 넣었다.
이렇게 Mcrypt를 통해 암호화를 하면 그 결과로 바이너리(Binary) 값을 반환한다. 즉, 컴퓨터만 이해할 수 있는 2진수 데이터를 반환한다는 의미다. 따라서 브라우저는 “‘ӫ�{3�ѠO#�c�ʾfBg�”와 같이 인간도, 브라우저도 이해할 수 없는 결과를 출력할 것이다.
이 문제는 base64_encode() 함수를 이용함으로써 해결할 수 있다. 결과적으로 “8UHT/jWsIopHDCUpbfJLIA==”와 같이 아스키 코드로 변환한 값을 얻을 수 있다. 이로써 암호화가 성공적으로 이루어졌다.
이제 복호화 코드를 보자.
1 | $decryptedDataOnBinary = base64_decode ( $encryptedData ); |
2 | $decryptedData = mcrypt_ecb(MCRYPT_GOST, $key , $decryptedDataOnBinary , MCRYPT_DECRYPT); |
3 | echo "바이너리 값으로 다시 변환한 암호화 결과 값 : " . $decryptedDataOnBinary ; |
4 | echo "<br/>" ; |
5 | echo "바이너리 값을 복호화 한 결과 값 : " . $decryptedData ; |
앞서 (아스키 코드로 까지) 암호화한 결과 값을 base64_decode() 함수를 이용해 다시 바이너리 값으로 변환한다. 이 값을 다시 mcrypt_ecb() 함수를 이용해 복호화 하기 위해, 앞서 암호화하기 위해 사용했던 알고리즘의 상수인 MCRYPT_GOST, 앞서 암호화 하기 위해 사용했던 키, 바이너리로 다시 변환한 암호화 결과 값, 복호화를 위한 상수 MCRYPT_DECRYPT를 넣는다. 그 결과로 복호화 된 결과 값인 $decryptedData를 출력하면 “개인정보”라는 문자열을 얻게 된다. 이로써 복호화도 성공적으로 이루어졌다.
위의 결과를 아래와 같이 함수로 정리하면 편리하게 사용할 수 있다.
01 | // mcrypt.php |
02 | <?php |
03 | $key = "1dasd12WESA12dsaasd456TGDFsd" ; |
04 |
05 | /** |
06 | * 데이터 암호화 함수 |
07 | */ |
08 | function function_for_encryption( $plain_data ){ |
09 | global $key ; |
10 | $encrypted_data_on_binary = mcrypt_ecb (MCRYPT_SERPENT, $key , $plain_data , MCRYPT_ENCRYPT); |
11 | $encrypted_data = base64_encode ( $encrypted_data_on_binary ); |
12 | return $encrypted_data ; |
13 | } |
14 |
15 | /** |
16 | * 데이터 복호화 함수 |
17 | */ |
18 | function function_for_decryption( $encrypted_data ){ |
19 | global $key ; |
20 | $decrypted_data_on_binary = base64_decode ( $encrypted_data ); |
21 | $plain_data = mcrypt_ecb (MCRYPT_SERPENT, $key , $decrypted_data_on_binary , MCRYPT_DECRYPT); |
22 | return $plain_data ; |
23 | } |
4. MCRYPT를 이용한 암호화/복호화를 DB 입력/조회에 적용하기
이제 암호화/복호화를 DB 입력/조회에 적용해 보겠다.
DB에는 mailing_list라는 테이블이 있고 그 안에 no, name, email, date라는 필드가 있고 no 필드는 int이며 Auto Increment, 나머지 필드는 모두 varchar라고 가정한다.
POST 값으로 다음과 같은 메일링리스트 가입 정보를 받았다고 가정하자.
1 | Array ( |
2 | [name] => testman |
3 | [email] => test@example .com |
4 | [date] => 20110521 |
5 | ) |
이제 POST로 넘겨받은 모든 값을 암호화 해서 DB에 입력할 것이다.
01 | // insertDB.php |
02 | <?php |
03 | include ./dbConnect.php; // DB 연결 (구체적인 코드는 생략한다) |
04 | include ./mcrypt.php; |
05 |
06 | foreach ( $_POST as $key => $value ) { |
07 | $_POST [ $key ] = function_for_encryption( $value ); |
08 | } |
09 | $query = "INSERT INTO `mailing_list` (`name`, `email`, ` date `) |
10 | VALUES ( '{$_POST[' name ']}' , '{$_POST[' email ']}' , '{$_POST[' date ']}' )"; |
11 | $result = mysql_query( $query ); |
이제 mailing_list 테이블의 모든 데이터를 조회해서 복호화 한 다음, 화면에 출력할 것이다.
01 | //selectDB.php |
02 | <?php |
03 | include ./dbConnect.php; //DB 연결 (구체적인 코드는 생략한다) |
04 | include ./mcrypt.php; |
05 | ?> |
06 |
07 | <h1>메일링리스트</h1> |
08 | <ul> |
09 | <?php |
10 | for ( $i =0; $i <mysql_num_rows( $result ); $i ++){ |
11 | $row = mysql_fetch_array( $result ); |
12 |
13 | foreach ( $row as $key => $value ) { |
14 | if ( $key == 'no' ) { |
15 | continue ; // $row['no']는 복호화 할 필요가 없다. |
16 | } |
17 | $row [ $key ] = function_for_decryption( $value ); |
18 | } |
19 | ?> |
20 | <li> |
21 | <p>번호 : <?= $row [ 'no' ]?></p> |
22 | <p>이름 : <?= $row [ 'name' ]?></p> |
23 | <p>이메일 : <?= $row [ 'email' ]?></p> |
24 | <p>신청일 : <?= $row [ 'date' ]?></p> |
25 | </li> |
26 | <?php}?> |
27 | </ul> |
mod_rewrite 설치
AllowOverride None -> AllowOverride All
<IfModule mod_rewrite.c>
RewriteEngine On RewriteBase / RewriteCond $1 !^(index\.php|images|captcha|data|include|uploads|robots\.txt) RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ /index.php/$1 [L] </IfModule>
PHP에서 MSSQL을 사용할 수 있도록 지원해주는 모듈이 있다. (freetds)
사이트에서 (http://freetds.schemamania.org/)
Stable Release 버전을 다운받는다. (ftp://ftp.astron.com/pub/freetds/stable/freetds-stable.tgz)
/usr/local/src# wget ftp://ftp.astron.com/pub/freetds/stable/freetds-stable.tgz
/usr/local/src# tar -zxvf freetds-stable.tgz
/usr/local/src/freetds# ./configure
--prefix=/usr/local/freetds
--with-tdsver=8.0
--disable-odbc
--disable-debug
--enable-dbmfix
--enable-msdblib
/usr/local/src/freetds# make
/usr/local/src/freetds# make install
freetds 설치가 완료되었다.
/usr/local/freetds/etc/freetds.conf 파일을 수정한다.
===========================================
[egServer70]
host = ntmachine.domain.com
port = 1433
tds version = 7.0
위 양식대로 연결할 서버 정보를 추가한다.
(tds version 은 어떻게 확인하는지 모르겠다.)
===========================================
PHP를 다시 컴파일 해서 설치한다. (phpize를 사용할 수 도 있지만 귀찮다.)
./configure 기존 옵션에 --with-mssql=/usr/local/freetds 를 추가한다. (기존 옵션은 phpinfo()로 확인.)
CodeIgniter config/database.php 정보
freetds.conf에 입력한 정보대로 hostname을 입력한다.
$db['default']['hostname'] = 'egServer70';
$db['default']['username'] = 'USERNAAME';
$db['default']['password'] = 'PASSWORD';
$db['default']['database'] = 'DATABASE';
$db['default']['dbdriver'] = 'mssql';
$db['default']['dbprefix'] = '';
$db['default']['pconnect'] = FALSE;
$db['default']['db_debug'] = TRUE;
$db['default']['cache_on'] = FALSE;
$db['default']['cachedir'] = '';
$db['default']['char_set'] = 'utf8';
$db['default']['dbcollat'] = 'utf8_general_ci';
$db['default']['swap_pre'] = '';
$db['default']['autoinit'] = TRUE;
$db['default']['stricton'] = FALSE;
Copyright © 2015-2025 Socialdev. All Rights Reserved.