728x90
반응형

PHP 기반으로 웹 서비스를 제공할 경우 실제 파일 시스템과 웹 서비스의 URL 이 일치하도록 제공하는 경우가 많았습니다.

만약 웹 서비스의 소스 디렉터리(DocumentRoot)가 /var/www/example.com 일 경우 다음과 같은 디렉터리를 만들고 웹 브라우저에서는 http://example.com/cart/view.php 를  호출할 경우 /var/www/example.com/cart/view.php 를 실행한 후 결과를 브라우저에 전송했습니다.

$ tree -f
.
├── ./cart
│   └── ./cart/view.php
└── ./user
├── ./user/login.php
└── ./user/regist.php

 

서비스의 URL은 "http://example.com/kb/index.php?cat=8&id=41" 처럼 URL 에 GET 파라미터를 넘겨서 웹 서비스를 호출하는게 일반적이었습니다.

 

이는 웹 서비스가 파일 시스템과 일치하여 종속적이 되고 URL 을 기억하기 어렵게 해서 사용자의 웹 접근성을 떨어뜨리는 문제가 있습니다. 

 

Pretty URLs 은 Clean URLs, user-friendly URLs 라고도 하며 "http://example.com/kb/8/41" 처럼 사용자가 기억하기 쉽고 파일 시스템과 분리된 URL 로 서비스를 제공하는 것을 의미하며 라라벨을 사용하면 간단하게 Pretty URLs 기반의 웹 서비스를 만들 수 있습니다.


출처 : https://www.lesstif.com/display/LIFE

728x90
반응형
728x90
반응형

PHP 로 웹 개발을 할 경우 뷰 레이어 코드를 작성할 때 HTML 내에  <?php echo $val; ?>  와 같이 데이타를 출력하는 코드를 넣는 것은 매우 귀찮고 실수할 여지가 많은 작업이었습니다.

 

라라벨은 blade 라는 심플하고 사용이 쉬운 템플릿(template) 엔진을 내장하고 있으므로 뷰 코드를 작성할 때 이런 수고를 더 이상하지 않고 MVC 패러다임에 맞는 개발을 할수가 있습니다.

템플릿 엔진

 

블레이드는 상속을 지원하므로 레이아웃이나 jQuery 를 포함하는 <script> 구문같이 페이지마다 공통적으로 계속 사용해야 하는 부분은 상속을 통해 체계적으로 관리할 수 있습니다.

 

블레이드 템플릿을 사용하면 HMTL 과 CSS 를 바로 사용하고 PHP 구문만 특정 태그로 처리하면 되므로 디자이너와 개발자간의 협업도 기존에 비해 용이해 집니다.

 

블레이드의 또 다른 장점중 하나는 뷰 레이어에 출력을 하기 위해 {{ }} 를 호출하면 e() 라는 헬퍼 함수로 변환하고 헬퍼 내부에서 htmlspecialchars() 호출을 통해 위험한 특수 문자열을 자동적으로 변환해 줍니다.

그러므로 뷰에 출력할 때마다 직접 htmlspecialchars() 로 필터링할 필요가 없으지므로 코드의 양이 줄고 혹시 모를 실수로 인해 XSS(Cross Site Script) 공격을 당할 위험을 줄여 줍니다.


출처 : https://www.lesstif.com/display/LIFE

728x90
반응형
728x90
반응형

이제 웹 개발시 보안은 "하면 좋고 안 해도 그만"인 요소가 아니라 고객과 비즈니스를 보호하기 위해서는 필수로 고려해야 하는 가장 중요한 부분중 하나가 되었고 이를 위해 개발팀이 우선적으로 고려해야 할 사항은 시큐어 코딩(Secure coding)입니다.

하지만 시큐어 코딩은 보안에 대한 일정 수준의 이해를 필요로 하며 바쁜 프로젝트 일정상 이를 고려하지 않고 개발이 되는 경우가 많은게 사실입니다.


라라벨은 프레임워크 차원에서 보안을 위해 여러 가지 기능을 제공하고 있으므로 주요 취약점들에 대해 어렵지 않게 대응이 가능합니다.


public 폴더 노출 최소화 및 설정 파일 숨김

기존의 PHP 웹 애플리케이션들은 애플리케이션이 파일 시스템과 매칭되는 경우가 많았고 이로 인해 웹 애플리케이션 구동에 필요한 설정 파일(DB 연결 정보, 파일 경로등)도 웹 서버에 위치시키는 경우가 많았습니다.

 


예로 다음 예제처럼 DB 연결 정보를 담고 있는 설정 파일을 require 로 사용할 경우를 생각해 봅시다.

<?php
  
require_once('conf/db_conn.inc');
  
connect_db(); 
?>

 

이 경우 브라우저에서 example.com/conf/db_conn.inc 를 바로 호출할 경우 DB 계정 정보가 노출되는 등의 보안 취약점이 존재할 위험이 있습니다.

이를 막기 위해서는 웹 서버가 특정 확장자(예: .inc, .htaccess)는 서비스하지 않도록 별도의 보안 설정을 해주거나 또는 웹 서버의 DocumentRoot 이외의 경로에 db_conn.inc 를 두고 애플리케이션에서 절대 경로로 읽어 들여야 합니다.

 

 이런 보안 취약점이 발생할 수 있는 여지를 차단하고자 라라벨은 구동에 필요한 설정 파일을 웹 서버의 DocumentRoot 와 격리하였으므로 설정 파일 유출에 따른 보안 문제를 최소화해 줍니다.


또 .php 의 직접 호출이 아닌 애플리케이션 라우팅을 통해 서비스를 제공하도록 설계되었고 public 폴더에는 단 하나의 PHP(index.php) 파일만 존재합니다.

이를 통해 public 폴더의 노출을 최소화하였고 .php 파일 직접 호출을 통한 공격이나 설정 파일을 브라우저에서 다운로드 받을 수 있는 취약점 발생 가능성을 최소화하였습니다.


SQL 삽입(SQL Injection) 공격

만약 사용자 id와 암호를 입력받아서 로그인을 처리하는 페이지가 있을 경우 SQL Injection 을 고려하지 않을 경우 다음과 같이 코딩하게 됩니다.

$sql="SELECT * FROM users WHERE userid='$userid' and password='$password'";
 
$result=mysql_query($sql);
$count=mysql_num_rows($result);
 
if($count==1){
    //login 성공
}
else {
    //login 실패
}

PHP 7 에서는 mysql 익스텐션이 삭제되었으므로 mysql_* 로 시작하는 함수들을 더 이상 사용할 수 없으며 대신 mysqli 나 pdo_mysql을 사용해야 합니다.


위와 같은 코드는 클라이언트가 보낸 문자열을 검증없이 사용하므로 공격자가 password 에  ' or '1' = '1 라는 문자열을 넣으면 or 뒤의 문장이 참이므로 id와 암호를 몰라도 관리자로 로그인이 가능해져 버립니다.

SQL 삽입 공격


라라벨은 이를 막기위해 모든 파라미터를 문자열로 처리하지 않고 PDO 변수에 바인딩하여 처리하므로  대부분의 SQL Injection 공격을 막아낼 수 있습니다.


라라벨의 DB 기능을 사용하여 사용자의 id 와 암호를 조회하기 위해 다음과 같이 코드를 작성했다고 가정해 보겠습니다.

DB::select('select * from users where id = :userid and password = :password', ['userid' => 'myid''password' => 'mypasswd']);


라라벨에서 DB 쿼리를 생성하는 기능을 제공하는 Query Builder  는 파라미터를 내부적으로 준비된 문장(Prepared Statement)와 매개변수 바인딩(Bound Parameter) 를 통해 다음과 같이 안전하게 실행됩니다.

$s $dbh->prepare('SELECT * FROM users WHERE userid = :userid and password = :password') ;
$s->bindParam(':userid '$userid );
$s->bindParam(':password'$password);

이제 공격자가 SQL 삽입 공격을 시도해도 입력한 문자는 이미 해석이 끝난 SQL 문에 파라미터로 전달되므로 aaa' or '1' = '1 를 입력해도 password 컬럼의 값이 aaa' or '1'='1' 인 레코드를 찾게되므로 개발자가 특별히 신경쓰지 않아도 기본적으로 SQL 삽입 공격을 방지할 수 있습니다.


그리고 사이트간 스트립팅(CSS 또는 XSS; Cross-site Scripting) 공격을 막기위해 view 단에 출력하는 데이타는 htmlentities() 함수로 변환하고 있으며(블레이드 템플릿에서 설명합니다.) 웹 애플리케이션의 가장 취약한 부분중 하나인 사이트간 요청 위조(CSRF; Cross-site request Forgery) 를 막기 위해 기본적으로 POST, DELETE, PUT 같이 서버의 데이타를 수정하거나 삭제할 가능성이 있는 액션에는 CSRF 토큰을 삽입하고 검증하고 있습니다.

이는 라라벨의 기본 기능이므로 애플리케이션 개발자는 VIEW 단에 CSRF 를 출력하는 코드인 csrf_token(); 만 추가하면 서버단에서 별도의 CSRF 검증 코드를 구현하지 않아도 CSRF 공격에 견고한 서비스를 만들 수 있습니다.


또 세션을 가로채서 공격하는 HTTP Session Hijacking 을 막기 위해 모든 세션 데이타는 강력한 알고리즘으로 암호화되어 저장됩니다.


라라벨이 제공하는 보안 기능에 대해서는 뒷 장 "세션과 보안/인증" 에서 자세히 살펴 보겠습니다.


출처 : https://www.lesstif.com/display/LIFE

728x90
반응형
728x90
반응형

데이타베이스 추상화

웹 개발 환경에서 데이타베이스는 굉장히 중요한 요소이며 PHP 는 MySQL, PostgreSQL, SQLite, MS-SQL Server, Oracle, Cubrid 등 다양한 DBMS 를 지원하고 있습니다. 

라라벨은 Java의 JDBC 처럼 DB 레이어를 추상화한 레이어인 PDO(PHP Data Objects) 를 사용하므로 mysql_fetch_array 나 oci_fetch_array 처럼 특정 벤더에 의존적이지 않은 함수를 사용하지 않고 데이타베이스 관련 코드를 작성할 수 있습니다.

또 의존성 주입을 사용하여 런타임에 사용할 DB 를 결정하므로 설정 변경만으로 사용하는 DBMS 종류를 변경할 수 있습니다.

라라벨 5는 공식적으로 MySQL, PostgreSQL, SQLite,  MS-SQL Server 4 가지 DBMS만 지원하고 있으며 그외 DB는 커뮤니티에서 작성한 것을 사용해야 합니다.

데이타 베이스 추상화

 


Query builder 와 ORM(Object Relation Mapping)  지원

라라벨은 쿼리 빌더 기능을  제공하고 있으므로 이를 사용하면 SQL 을 사용하지 않고 손쉽게 데이타베이스와 작업을 할 수 있습니다.

 

다음은 고객 테이블에서 특정 이메일 주소를 갖는 고객 정보를 가져온 후에 이메일 인증 여부 필드를 true 로 설정하는 예제입니다.

DB::table('customers')
            ->where('email''user@example.com')
            ->update(['confirmed' => true]);

 

라라벨은 루비온레일스의 Active Record 와 동일한 역할을 수행하는 Eloquent라는 ORM을 통해 PHP 모델 클래스와 데이타베이스의 테이블을 손쉽게 연계할 수 있으며 SQL 구문 없이 데이타간의 다양한 관계를 표현할 수 있으므로 특정 DBMS 에 의존적이지 않으며 DB의 컬럼 추가/수정/삭제등 변경이 발생해도 코드의 수정이 최소화되는 애플리케이션을 작성할 수 있습니다.

 

Eloquent ORM

 

출처 : https://www.lesstif.com/display/LIFE

728x90
반응형
728x90
반응형

MVC 는 비즈니스 로직과 사용자 뷰 영역을 분리하기 위한 소프트웨어 개발 패턴입니다. 과거의 php 는 MVC 를 따르지 않고 한 파일에 모든 로직을 기술하는 형식으로 개발되는 경우가 많았습니다.


예로 다음은 GET 파라미터에 따라 직원 db 에서 직원을 검색하거나 삭제하는 PHP 예제입니다.

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
<?php
$con = mysql_connect("localhost""laravel""homestead");
if (!$con) {
    die('Could not connect: ' . mysql_error());
}
 
$mode $_GET["mode"];
if ($mode == "list") {
    mysql_select_db("laravel"$con);
    $result = mysql_query("SELECT * FROM users");
    echo "<table border='1'>
    <tr>
    <th>user_id</th>
    <th>user_name</th>
    <th>email</th>
    </tr>";
    while ($row = mysql_fetch_array($result)) {
        echo "<tr>";
        echo "<td>" $row['id'] . "</td>";
        echo "<td>" $row['name'] . "</td>";
        echo "<td>" $row['email'] . "</td>";
        echo "</tr>";
        echo "\r\n";
    }
    echo "</table>";
else if ($mode == "delete") {
    $result = mysql_query("DELETE FROM users where id = " .  $_GET["user_id"]);
    echo "delete done!";
}
mysql_close($con);
?>

위 코드는 $mode 의 값의 설정 여부에 따라 다른 동작을 하고 있으며 비즈니스 로직과 db 에서 가져온 모델, 그리고 처리 결과를 보여주는 뷰 로직이 하나의 파일에 작성되어 있습니다.

이는 소프트웨어의 규모가 증가할 수록 복잡도를 늘리고 수정이 어려워지며 문제가 발생할 경우 디버깅도 매우 힘들어 지게 됩니다.


비즈니스 로직을 구현한 애플리케이션 코드와 이를 사용자에게 전달하기 위한 화면 디자인은 필요한 기술과 능력이 다르므로 각 분야의 전문가가 분업하는게 품질과 효율성이 높아집니다.

규모가 있는 프로젝트이면 개발자와 디자이너가 별도로 존재하나 하나의 파일에 비즈니스 로직과 화면 디자인이 존재한다면 디자이너가 화면의 디자인을 변경하기 위해서는 개발자의 도움이 필요하고 개발자가 코드를 수정하기 위해서는 디자이너의 도움이 받아야 하는등 작업 효율이 나빠지고 자기가 전문 분야가 아닌 부분의 내용을 만져야 하므로 품질도 떨어질 우려가 있습니다.

MVC가 없을 경우

MVC 가 없을 경우
대부분의 웹 프레임워크는 기본적으로 MVC 기능을 탑재하고 있듯이 라라벨도 MVC 를 제공하고 있으며 라라벨 MVC 는 가볍고 사용이 쉽고 유연하므로 비즈니스 로직과 디자인을 분리하고 간결하고 우아하고 유지보수가 용이한 코드를 작성할 수 있습니다.

MVC 패턴


다음은 위의 기존 코드를 라라벨 MVC 를 활용하여 작성할 때의 일반적인 모습으로 컨트롤러에서 모델을 생성하고 이를 뷰에 전달하여 코드가 간결하고 우아하며 기능이 분리되므로 코드 작성이 쉽고 유지보수가 용이한 것을 짐작할수 있습니다.


UserController.php
<?php namespace App\Http\Controllers;
  
class UserController extends Controller 
{
    // 사용자 목록 보기   
    public function list()
    {
        $list = User::findAll();
        return view('user.list')->with('list'$list);
    }
  
    // 사용자 삭제
    public function delete($id)
    {
        User::delete($id);
        return view('user.delete');
    }
}


user.list.php

<html>
    <body>
        <h1>User List</h1>
        <?php foreach ($list as $u): ?>
            <li> <?php echo $u['name']; ?> </li>
        <?php endforeach; ?>
    </body>
</html>


출처 : https://www.lesstif.com/display/LIFE

728x90
반응형

+ Recent posts