136
1 實戰 CodeIgniter PHP Framework Bo-Yi Wu (appleboy) 2014.09.26 成功大學電算中心

You must know about CodeIgniter Popular Library

Embed Size (px)

DESCRIPTION

實戰 CodeIgniter

Citation preview

1

實戰 CodeIgniter PHP Framework

Bo-Yi Wu (appleboy)2014.09.26

成功大學電算中心

2

關於我

Bo-Yi Wu (appleboy)– Blog: http://blog.wu-boy.com/– Github: https://github.com/appleboy– CodeIgniter 站長– Laravel 站長

3

為什麼要使用 FrameworkWhy should I use a framework ?

4

不用重新造輪子Not having to reinvent the wheel

5

容易升級與維護upgradability and maintenance

6

既定開發流程Develop Flow

7

網站安全性Web Security

8

網站安全性

• 管理介面 URL● 目錄 (Index of) ● 錯誤訊息● 暫存測試資訊● 版本控管● SQL Injection

9

Joomla 管理介面

10

早期 phpMyAdmin 有漏洞風險

11

常用管理介面路徑

● /admin/● /phpMyAdmin/● /adminLogin/● /manage/● /management/● /root/● /wp-admin/

政府機關、學校機構、電信業者

12

如何防禦

● 限制存取 IP(Apache, Nginx)● 隱藏管理介面 ( 複雜目錄名稱 )● 增加後台防禦 (Captcha …)

13

網站安全性

● 管理介面 URL• 目錄 (Index of) ● 錯誤訊息● 暫存測試資訊● 版本控管● SQL Injection

14

15

Index of

● 網路目錄結構曝光● 存取敏感檔案

– .bak– config.php.bak– .svn, .git, – database.yml

16

如何防禦

關閉 Index 功能 (Apache) <Directory /> Options -Indexes </Directory>

17

網站安全性

● 管理介面 URL● 目錄 (Index of) • 錯誤訊息● 暫存測試資訊● 版本控管● SQL Injection

18SQL 錯誤訊息

19

如何防禦

● 關閉錯誤顯示– php.ini– display_errors = off

● 使用 Framework 都可以直接設定在專案裡

20

網站安全性

● 管理介面 URL● 目錄 (Index of) ● 錯誤訊息• 暫存測試資訊● 版本控管● SQL Injection

21

暫存測試資訊

● 開發者求方便使用檔名備份– .bak, xxx.php2

● 編輯器自動備份– index.php~, index.php.swp

● 看系統資訊– phpinfo.php

22

不要在 Production 機器上改程式碼

set vim :set nobackup

23

如何防禦

● 不要在正式產品環境中進行開發● 關閉編輯器自動備份● 伺服器過濾檔案下載

– Nginx

# Prevent clients from accessing to backup/config/source fileslocation ~* (?:\.(?:bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist)|~)$ { deny all;}

24

網站安全性

● 管理介面 URL● 目錄 (Index of) ● 錯誤訊息● 暫存測試資訊• 版本控管● SQL Injection

25

版本控管

http://xxxx.com/.git/confighttp://xxxx.com/.githttp://xxxx.com/.svn

26

27

如何防禦

● 開發環境跟正式環境切開● 禁止版本控制資料夾存取● 導入 Deploy 流程 (Continuous Integration)

28

網站安全性

● 管理介面 URL● 目錄 (Index of) ● 錯誤訊息● 暫存測試資訊● 版本控管• SQL Injection

29

SQL Injection

SELECT id FROM users WHERE email = ‘$email‘ and password = ‘$password’;

SELECT id FROM users WHERE email = ‘$email‘ and password = ‘anything' OR ‘1’ = ‘1’;

30

如何防禦

● 請不要相信使用者任何輸入字串● 正規比對格式

– preg_match(‘/^(\w)+$/’, $string);– 使用 framework 提供 escape 函式

● 型態轉換 Typecasting

31

型態轉換 Typecasting

$var = (array) $var;$var = (binary) $var;$var = (bool) $var;$var = (boolean) $var;$var = (double) $var;$var = (float) $var;$var = (int) $var;$var = (integer) $var;$var = (object) $var;$var = (real) $var;$var = (string) $var;

32

選擇 PHP Framework

33

34

35

為什麼要選擇 CodeIgniter

● 安裝容易● 輕易上手● 繁中文件

36

安裝容易wget + unzip = done

37

輕易上手只要會一點點物件導向即可

38

繁中文件目前只有 CodeIgniter 、 Laravel 有繁中文件

http://codeigniter.org.tw/user_guide/http://bit.ly/ci-userguide

39

CodeIgniter3.0 發展

目前最新為 2.2.0 版本

40

EllisLab Seeking New Owner for CodeIgniter

http://bit.ly/ci-seek-new-owner

41

42

3.0 版本有超過100 個 bug fixed

100 個 feature commit

http://bit.ly/ci-changelog

43

CodeIgniter架構

44

CodeIgniter 架構

● application 開發 MVC 程式碼● system 系統程式碼● user_guide 線上文件● index.php 主檔案

45

index.php

● $application_folder = 'application';● $system_path = 'system';

46

更動 Web 架構

47

CodeIgniter 架構

● application● system● public/index.php● public/robots.txt● Public/.htaccess

48

index.php

● $application_folder = ‘../application';● $system_path = ‘../system';

49

使用者無法存取 index.php 以外的檔案

Apache: DocumentRoot /xxx/publicNginx: root /xxx/public

50

隱藏 URL index.php 字串

51

ApacheRewriteEngine onRewriteBase /RewriteCond $1 !^(index\.php|robots\.txt|$)RewriteRule ^(.*)$ index.php/$1 [L,QSA]

52

Nginxlocation / { try_files $uri $uri/ /index.php?$query_string;}

53

使用此架構好處

● 避免 .git 曝露

● 根目錄可以放其他設定檔– .editorconfig– .gitignore– gulpfile.coffee– bower.js– package.json

54

作業一

● 建立一個 virtual host: ci.localhost● 安裝 codeigniter 2.2.0● 移除 url 的 index.php 字串

– http://ci.localhost/welcome

55

CodeIgniter 核心架構

56

核心架構● core

– Controller, Model, Router, Loader, Input …● database

– MySQL, ODBC, MSSQL, Sqlite …● helpers

– email, url, text, number, language …● language

– zh-tw, zh-cn, english …● libraries

– Form, Image, Session, Email, Pagination

57

核心函式不夠用擴充核心函式庫

58

擴充核心函式庫

● core– MY_Model, MY_Controller, MY_Input ….

● libraries– MY_Email, MY_Upload ….

● helpers– MY_array_helper ….

59

$this->load->library('email');

系統讀取流程

60

讀取優先順序

● application/libraries/MY_Email.php● application/libraries/Email.php● system/libraries/Email.php● application/libraries/MY_email.php● application/libraries/email.php● system/libraries/email.php

61

擴充 Native Session

支援原生 $_SESSIONhttp://bit.ly/ci-native-session

62

3.0 版本已經支援Native Session

63

安裝$ cp config/session.php application/config/ $ cp libraries/Session.php application/libraries/

64

多個 Application 請設定 config

$config['sess_namespace'] = '';

65

多國語系 i18nhttp://bit.ly/ci-i18n

66

擴充 Core Language$ cp application/config/language.php app/application/config/ $ cp application/core/MY_Lang.php app/application/core/

67

設定

$config['language_field'] = 'lang';$config['language_key'] = 'en-us'; $config['language_list'] = array( 'en-us' => 'english', 'zh-tw' => 'zh-tw‘);

68

使用方式

$this->load->helper('language');$this->lang->load('welcome');echo lang('welcome.title');

69

作業二

● 將 Welcome controller 加入– Native Session– 多國語言

70

PHP ORM ModelCodeIgniter 沒有 ORM

只有 ActiveRecord

71

Codeigniter Base Modelhttp://bit.ly/ci-base-model

72

簡介class Topic_model extends MY_Model { } $this->load->model('topic_model', 'topic');$this->topic->get_all();$this->topic->get(1);$this->topic->get_by('title', 'Pigs CAN Fly!');$this->topic->get_many_by('status', 'open');

$this->topic->insert(array( 'status' => 'open', 'title' => "I'm too sexy for my shirt"));

$this->topic->update(1, array( 'status' => 'closed' ));$this->topic->delete(1);

73

擴充核心 Model下載 MY_Model.php 放到

application/core

74

class Topic_model extends MY_Model { } class Topic_m extends MY_Model { }

命名原則

75

指定資料表

class Topic_model extends MY_Model { public $_table = ‘topics’; }

76

指定 Primary Key

// 預設為 idclass Topic_model extends MY_Model{ public $primary_key = ‘topic_id'; }

77

Callbacks

● $before_create ● $after_create ● $before_update ● $after_update ● $before_get ● $after_get ● $before_delete ● $after_delete

78

範例

class Topic_model extends MY_Model{ public $before_create = array( 'timestamps' );

protected function timestamps($topic) { $topic['created_at'] = date('Y-m-d H:i:s'); $topic['updated_at'] = date('Y-m-d H:i:s'); return $topic; }}

79

參數處理

public $before_create = array('data_process(name)');public $before_update = array('data_process(date)');

protected function data_process($row){ $row[$this->callback_parameters[0]] = $this-

>_process($row[$this->callback_parameters[0]]);

return $row;}

80

驗證 Validation

class User_model extends MY_Model{ public $validate = array( array( 'field' => 'email', 'label' => 'email', 'rules' => 'required|valid_email|is_unique[users.email]' ), array( 'field' => 'password', 'label' => 'password', 'rules' => 'required' ), array( 'field' => 'password_confirmation', 'label' => 'confirm password', 'rules' => 'required|matches[password]' ), );}

81

新增修改資料都會觸發驗證

82

忽略資料驗證$this->user_model->skip_validation();

$this->user_model->insert(['email' => 'blah'], true);

83

保護欄位

class Topic_model extends MY_Model{ public $protected_attributes = ['id'];}

84

$this->topic_model->insert(array( 'id' => 2, 'title' => 'A new topic'));

// INSERT INTO topics (title) VALUES ('A new topic')

85

Object vs. Array

class Topic_model extends MY_Model{ protected $return_type = 'array';}

86

$this->topic_model ->as_array() ->get(1);$this->topic_model ->as_object() ->get_by('column', 'value');

87

Soft Delete

class Topic_model extends MY_Model{ protected $soft_delete = true; protected $soft_delete_key = 'deleted';}

88

$this->topic_model->get(1); // SELECT * FROM topics WHERE id = 1 and

deleted = 0 $this->topic_model->only_deleted()->get(1); // SELECT * FROM topics WHERE id = 1 AND

deleted = 1 $this->topic_model->with_deleted()->get(1); // SELECT * FROM topics WHERE id = 1

89

內建 Observers

class Topic_model extends MY_Model{ public $before_create = ['created_at',

'updated_at']; public $before_update = ['updated_at'];}

90

資料庫連線

class Topic_model extends MY_Model{ public $_db_group = 'group_name';}

91

作業三

● 實做最新消息系統– 建立 topics 資料表

● id, title, description, is_feature, created_at, updated_at

● 實做 CRUD ( 新增 , 刪除 , 修改 , 查詢 )● 實做置頂功能

92

Relationships

class Topic_model extends MY_Model{ public $belongs_to = ['user']; public $has_many = ['comments'];}

93

新增相關 Model

● class User_model extends MY_Model { }● class Comment_model extends MY_Model { }

94

指定相關資料表

class Topic_model extends MY_Model{ public $belongs_to = ['user' => ['model' =>

'user_m']]; public $has_many = ['comments' => ['model'

=> 'model_comments']];}

95

讀取資料

$topic = $this->topic_model ->with(user') ->with('comments') ->get(1);

echo $topic->user->name;

foreach ($topic->comments as $comment) { echo $message;}

96

SQL 表示

● SELECT * FROM users WHERE id = $topic->user_id

● SELECT * FROM comments WHERE topic_id = $topic->id

97

更換 Primary Key

class Topic_model extends MY_Model{ public $belongs_to = ['user' => ['primary_key' => 'post_user_id']]; public $has_many = ['comments' => ['primary_key' => 'parent_topic_id']];}

98

作業四

● 實做最新消息系統– 建立 Users 資料表

● id, username– 增加欄位在 Topic 資料表

● user_id – 顯示使用者帳號在 Topic列表

99

會員模組http://bit.ly/ci-ion-auth

100

功能列表

● 會員登入 (支援帳號或電子郵件 )● 會員登出● 會員註冊 ● 會員更新● 忘記密碼● 電子郵件認證● 會員群組權限● 驗證登入錯誤次數

101

安裝方式複製相關檔案到對應目錄

102

設定檔資料表

$config['tables']['users'] = 'users';$config['tables']['groups'] = 'groups';$config['tables']['users_groups'] = 'users_groups';$config['tables']['login_attempts'] = 'login_attempts';$config['join']['users'] = 'user_id';$config['join']['groups'] = 'group_id';

103

會員認證設定$config['admin_email'] = "[email protected]"; $config['default_group'] = 'members'; $config['admin_group'] = 'admin'; $config['identity'] = 'email'; $config['min_password_length'] = 8; $config['max_password_length'] = 20; $config['email_activation'] = FALSE; $config['manual_activation'] = FALSE; $config['remember_users'] = TRUE; $config['user_expire'] = 86500; $config['user_extend_on_login'] = FALSE; $config['track_login_attempts'] = FALSE; $config['track_login_ip_address'] = TRUE; $config['maximum_login_attempts'] = 3; $config['lockout_time'] = 600; $config['forgot_password_expiration'] = 0;

104

電子郵件表單

$config['email_templates'] = 'auth/email/';$config['email_activate'] = 'activate.tpl.php';$config['email_forgot_password'] = 'forgot_password.tpl.php';$config['email_forgot_password_complete'] = 'new_password.tpl.php';

105

自訂錯誤訊息

● $config['message_start_delimiter'] = '<p>'; ● $config['message_end_delimiter'] = '</p>'; ● $config['error_start_delimiter'] = '<p>';● $config['error_end_delimiter'] = '</p>';

106

Template模組A Lightweight Codeigniter Template Libray

http://bit.ly/ci-template

107

安裝方式$ php tools/spark install -v1.0.4 codeigniter-

template

108

預設模板$config['template_layout'] = 'template/layout';

109

新增 CSS連結$this->template->add_css("/min.css", "screen");

// <link href="/min.css" rel="stylesheet" type="text/css" media="screen" />

110

新增 JavaScript連結$this->template->add_js("/index.js", true);// <script src="/index.js" type="text/javascript"></script>

111

動態新增 Meta Tag$this->template->add_meta_tag("og:title", "Test Title",

'property');//output <meta property="og:title" content="Test Title" /> $this->template->add_meta_tag("keywords", "some

keywords"); // output <meta name="keywords" content="some

keywords" />

112

動態標題$this->template->add_title_segment('test');// output <title>test | your site title</title>

113

動態設定值$this->template->set("is_login", false);

or$this->template->is_login = false;

114

$this->template->render('index', $data);

輸出畫面

115

作業五

● 整合會員到最新消息系統– 登入後才可以修改及發表– 管理者才可以刪除文章

● 整合 Template模組– 加入 jQuery元件 http://jquery.com/– 加入 Bootstraphttp://getbootstrap.com/

116

CodeIgniter RESTful API Design

117

RESTful Representational State Transfer

各大網站 Google Amazone Yahoo 都提供 RESTful API

118

HTTP Methods

● GET => 讀取● PUT => 更新● POST => 新增● DELETE => 刪除

120

JSON usage in JavaScript

var output = { ‘title’: ‘I am appleboy.’, ‘desctiption’: ‘CodeIgniter in Action.’};

121

JSON usage in PHP

json_encode* http://bit.ly/php-json-encode

json_decode* http://bit.ly/php-json-decode

122

傳統

● /topic/create ● /topic/show/1 ● /topic/update/1 ● /topic/destroy/1

123

傳統

● /topic/create ● /topic/show/1 ● /topic/update/1 ● /topic/destroy/1

現在

● POST /topic● GET /topic/1 ● PUT /topic/1 ● DELETE /topic/1

124

CodeIgniter RESTful Server

http://bit.ly/ci-reset-server

125

安裝方式

● application/libraries/Format.php● application/libraries/REST_Controller.php● application/config/rest.php

126

範例

class Topic extends REST_Controller{ public function index_get() { // Display all topics } public function index_post() { // Create a new topic }}

127

參數

● $this->get('blah'); // GET ● $this->post('blah'); // POST ● $this->put('blah'); // PUT ● $this->delete('blah'); // DELETE

128

Response回覆

public function index_delete($id)

{

$this->response([

'returned from delete:' => $id,

]);

}

129

Response回覆

● // Send an HTTP 201 Created● $this->response($book, 201);● // HTTP 404 Not Found● $this->response([]);

130

支援 API Keys

● $config['rest_enable_keys'] = TRUE;

131

建立 API KEY 資料表

CREATE TABLE `keys` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`key` varchar(40) NOT NULL,

`level` int(2) NOT NULL,

`ignore_limits` tinyint(1) NOT NULL DEFAULT '0',

`date_created` int(11) NOT NULL,

PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

132

測試 API KEY

$ curl -X POST -H "X-API-KEY: some_key_here" http://example.com/topics

133

作業六

● 實作 Topic RESTful API 撰寫– /api/topic GET 新聞列表– /api/topic/{id} GET單一新聞列表– /api/topic/{id} PUT 更新新聞– /api/topic POST 建立新聞– /api/topic/{id} DELETE刪除新聞

● 用 jQuery AJAX搭配後端 CRUD 功能● 整合 Facebook登入 API

134

作業程式碼

https://github.com/appleboy/CodeIgniter-App

135

參考文獻

● CodeIgniter 台灣官網– http://codeigniter.org.tw/

● 被遺忘的資訊洩漏-重點回顧– http://goo.gl/UO7Akz

136

謝謝大家參與謝謝主辦單位