常用的超全局变量
session_set_cookie_params(5, '/', 'localhost');
session_start();
// $GLOBALS包含自身,故不在此列
foreach ([$_POST, $_GET, $_REQUEST, $_COOKIE, $_SESSION, $_SERVER, $_FILES] as $globalVar)
{
printArray($globalVar);
}
function printArray($arr)
{
if (is_array($arr) && !empty($arr)) {
foreach ($arr as $key => $val) {
if (is_array($val))
printArray($val);
else
echo $key . ":" . $val . "<br />";
}
}
}
什么是RESTful
Representational State Transfer 表现层状态转化
什么是RESTful架构:
- 每一个URI代表一种资源
- 客户端和服务器之间,传递这种资源的某种表现层
- 客户端通过四个HTTP动词,对服务器端资源进行操作,实现”表现层状态转化”
- GET用来获取资源
- POST用来新建资源(也可以用于更新资源)
- PUT用来更新资源
- DELETE用来删除资源
POST和GET区别
- 根据HTTP规范,GET用于获取信息,POST用于新建或更新
- GET请求数据附在URL上,POST请求数据放在request body中,只是位置不同
- 二者本质上无差别,都是通过TCP将数据从客户端传递到服务器端
- 数据量大小的限制是浏览器和服务器决定的,跟是什么请求无关
HTTP状态码
常见的HTTP状态码
- 200 - 请求成功
- 301 - 资源(网页等)被永久转义到其他URL
- 404 - 请求的资源(网页等)不存在
- 505 - 内部服务器错误
HTTP状态码分类
- 1** - 信息,服务器收到的请求,需要请求者继续执行操作
- 2** - 成功,操作被成功接收并处理
- 3** - 重定向,需要进一步的操作以完成请求
- 4** - 客户端错误,请求包含语法错误或者无法完成请求
- 5** 服务器错误,服务器在处理请求的过程中发生了错误
时间函数,打印出前一天、前一个月、明天等时间
echo date("Y-m-d H:i", strtotime('-1 year')) . "\n";
echo date("Y-m-d H:i", strtotime('-1 month')) . "\n";
echo date("Y-m-d H:i", strtotime('-1 week')) . "\n";
echo date("Y-m-d H:i", strtotime('-1 day')) . "\n";
echo date("Y-m-d H:i", strtotime('1 day')) . "\n";
如何实现字符串反转
英文
strrev($string)
中文(或包含英文)
$str = "使用Python可以更直观描述Algorithm"; $len = mb_strlen($str) - 1; $reversed = ''; while ($len >= 0) { $reversed .= mb_substr($str, $len--, 1); } echo $reversed; // mhtiroglA述描观直更以可nohtyP用使
数据库优化
ORM
ORM
- 定义:Object Relation Mapping
- 作用
- 关系型数据库和对象之间作一个映射
- MVC 模式实现了架构上将表现层(即View)和数据处理层(即Model)分离的解耦合,而持久化的设计则实现了数据处理层内部的业务逻辑和数据逻辑分离的解耦合
- 举例:Doctrine ORM
如何实现中文截取无乱码
mb_strlen() mb_substr()
模板引擎原理
用PHP写出显示客户端IP与服务器IP
// get client and server ip
echo gethostbyname('uatwww.blockbi.com');
/**
[SERVER_NAME] => www.test.local
[SERVER_PORT] => 80
[SERVER_ADDR] => 127.0.0.1
[REMOTE_PORT] => 50847
[REMOTE_ADDR] => 127.0.0.1
[SERVER_SOFTWARE] => nginx/1.11.5
[GATEWAY_INTERFACE] => CGI/1.1
[SERVER_PROTOCOL] => HTTP/1.1
*/
print_r($_SERVER);
require 和 include区别,require_once和require区别
require
和include
几乎完全一样,除了处理失败的方式不同之外。require
在出错时产生 E_COMPILE_ERROR级别的错误。换句话说将导致脚本中止而include
只产生警告(E_WARNING),脚本会继续运行。 - php.net
require_once
语句和require
(语句完全相同,唯一区别是 PHP 会检查该文件是否已经被包含过,如果是则不会再次包含。 - php.net
Input:
/**
* index.php
* $mark = 0;
* echo ++$mark . ': ' . __FILE__ . "\n";
*/
require 'index.php'; // echo __FILE__ . "\n";
echo ++$mark . ':' . __FILE__ . "\n";
require 'index.php';
echo ++$mark . ':' . __FILE__ . "\n";
Output:
1: /usr/local/var/www/test/index.php
2:/usr/local/var/www/test/test.php
1: /usr/local/var/www/test/index.php
2:/usr/local/var/www/test/test.php
Input:
/**
* index.php
* $mark = 0;
* echo ++$mark . ': ' . __FILE__ . "\n";
*/
require_once 'index.php'; // echo __FILE__ . "\n";
echo ++$mark . ':' . __FILE__ . "\n";
require_once 'index.php';
echo ++$mark . ':' . __FILE__ . "\n";
Output:
1: /usr/local/var/www/test/index.php
2:/usr/local/var/www/test/test.php
3:/usr/local/var/www/test/test.php
echo print print_r区别
echo和print都是语言结构
echo 可一次打印多个值,没有返回值
echo 'dog ', 'cat ', 'lion';
print一次只能一个值,返回值恒为1
print 'hello';
print_r通常用来打印数组
print_r (range(1,10));
传值和传引用
- 传值复制一个变量的副本
- 引用表示两个变量名指向同一个内容
MVC
什么是MVC
- Model
- View
- Controller
MVC优点
- 应用分层处理,降低耦合
- 开发人员平行工作,降低阻塞,提升效率
MVC不足
针对网站高并发大流量的解决方案
- 服务器
- 硬件升级
- 负载均衡
- 服务器集群
- 使用CDN(Content Delivery Network)内容分发网络
- 应用服务器和图片服务器分离
- 数据库
- 读写分离
- 分表
- 垂直切分
- 水平切分
- 缓存
- 页面缓存(静态化)
- 数据缓存
- redis
- memcache
- 访问
- 禁止外部盗链
- 控制大文件下载
- 程序
- 使用队列延迟处理数据
参考
- http://blog.csdn.net/yuxianjun2012/article/details/54846230
读取一个URL的内容
// m1
$url = "https://www.baidu.com";
$content1 = file_get_contents($url);
// m2
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://www.baidu.com');
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$content2 = curl_exec($ch);
if (false === $content2)
echo 'curl error:' . curl_error($ch);
error_reporting
// Turn off all error reporting
error_reporting(0);
// Report simple running errors
error_reporting(E_ERROR | E_WARNING | E_PARSE);
// Reporting E_NOTICE can be good too (to report uninitialized
// variables or catch variable name misspellings ...)
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
// Report all errors except E_NOTICE
error_reporting(E_ALL & ~E_NOTICE);
// Report all PHP errors (see changelog)
error_reporting(E_ALL);
// Report all PHP errors
error_reporting(-1);
// Same as error_reporting(E_ALL);
ini_set('error_reporting', E_ALL);
验证邮件格式
$pattern = '/^[A-Za-z0-9_-]+@[A-Za-z0-9_-]+(\.[A-Za-z0-9_-]+)+$/';
$emails = [
'1234@qq.com',
'kon@163.com',
'hello@world.net.cn'
];
foreach ($emails as $email) {
if (preg_match($pattern, $email))
echo $email . " is valid \n";
}
echo "\n";
// match Chinese
$chinesePattern = '/[\x{4e00}-\x{9fa5}]+/u';
if (preg_match($chinesePattern, '蝙蝠侠大战超人'))
echo 'Chinese matched';
else
echo 'Chinese not matched';
echo "\n";
// match email with Chinese included
$pattern = '/^[A-Za-z0-9\x{4e00}-\x{9fa5}_-]+@[A-Za-z0-9_-]+(\.[A-Za-z0-9_-]+)+$/u';
if (preg_match($pattern, '张三phper@qq.com'))
echo 'matched';
else
echo 'not matched';
当前脚本路径及其他常量
trait sayLuckyNumber
{
static function sayNumber()
{
echo 'Trait is ' . __TRAIT__ . "\n";
echo 'Your lucky number is ' . mt_rand() . "\n";
}
}
class SaySomething
{
use sayLuckyNumber;
private $something;
public function __construct($something)
{
$this->something = $something;
}
public function say()
{
echo 'Class is ' . __CLASS__ . "\n";
echo 'Method is ' . __METHOD__ . "\n";
echo $this->something . "\n";
}
}
$saySomething = new SaySomething('Hello Universe');
$saySomething->say();
$saySomething::sayNumber();
echo __FILE__ . "\n";
echo __DIR__ . "\n";
GD库
获取标准URL中的文件扩展名 ��
例如: http://symfony.com/images/v5/logos/sf-positive.svg
$url = 'http://symfony.com/images/v5/logos/sf-positive.svg';
/**
* Array
(
[scheme] => http
[host] => symfony.com
[path] => /images/v5/logos/sf-positive.svg
)
*/
$parsedUrl = parse_url($url);
/**
* Array
(
[dirname] => /images/v5/logos
[basename] => sf-positive.svg
[extension] => svg
[filename] => sf-positive
)
*/
$pathInfo = pathinfo($parsedUrl['path']);
echo $pathInfo['extension'];
算出两个文件的相对路径
遍历一个文件夹下的所有文件夹和文件
function showFiles($dirPath)
{
if (!is_dir($dirPath))
return;
if (substr($dirPath, strlen($dirPath) - 1, 1) != '/')
$dirPath .= '/';
$files = glob($dirPath . '*', GLOB_MARK);
foreach ($files as $file) {
if (is_dir($file)) {
showFiles($file);
} else
echo $file . "\n";
}
}
$dirPath = './vendor';
showFiles($dirPath);
OOP版
class ShowDir
{
private $dir;
private $step;
private $mark = '- ';
public function __construct($dir, $step = 1)
{
$this->dir = $dir;
$this->step = $step;
}
public function show()
{
if (!is_dir ($this->dir))
return;
if (substr ($this->dir, -1, 1) != DIRECTORY_SEPARATOR)
$this->dir .= DIRECTORY_SEPARATOR;
$files = glob ($this->dir . '*', GLOB_MARK);
foreach ($files as $file) {
$dirs = [];
if (is_dir ($file))
$dirs[] = $file;
else
echo str_repeat ($this->mark, $this->step) . $file . PHP_EOL;
}
if (!empty($dirs)) {
foreach ($dirs as $dir) {
echo str_repeat ($this->mark, $this->step) . $file . PHP_EOL;
$self = new self($dir, ++$this->step);
$self->show ();
}
}
}
}
$showDir =new ShowDir(__DIR__);
$showDir->show ();
打开php.ini中的Safe_mode,会影响哪些参数?至少说出6个
写个函数用来对二维数组排序
$arr = [
[
'name' => 'apple',
'size' => 1.4,
'color' => 'red'
],
[
'name' => 'pear',
'size' => 2.5,
'color' => 'white'
],
[
'name' => 'banana',
'size' => 1.1,
'color' => 'yellow'
],
[
'name' => 'watermelon',
'size' => 5.5,
'color' => 'green'
],
[
'name' => 'grape',
'size' => 1.4,
'color' => 'purple'
]
];
// usort
uasort($arr, function($a, $b){
if ($a['size'] == $b['size'])
return 0;
// asc
return $a['size'] < $b['size'] ? -1 : 1;
// desc
//return $a['size'] < $b['size'] ? 1 : -1;
});
var_dump($arr);
写个函数来解决多线程同时读写一个文件的问题
加锁
function writeFileWithLock($fp, $i)
{
if (flock($fp, LOCK_EX)) {
while ($i >= 0) {
fwrite($fp, $i . ' ');
$i--;
sleep(1);
}
flock($fp, LOCK_UN);
}
}
$fork = pcntl_fork();
$file = 'test.txt';
$fp = fopen($file, 'ab+');
if ($fork == 0) {
// 子进程
writeFileWithLock($fp, 10);
} else {
// 主进程
writeFileWithLock($fp, 7);
}
terminal执行,检查进程
ps aux | grep p1.php
will 2701 0.0 0.0 2432804 1976 s003 S+ 8:37上午 0:00.01 grep p1.php
will 2697 0.0 0.0 2472792 1204 s002 S+ 8:37上午 0:00.00 php p1.php
will 2696 0.0 0.2 2471768 13508 s002 S+ 8:37上午 0:00.02 php p1.php
主进程执行完毕后,检查进程
ps aux | grep p1.php
will 2703 0.0 0.0 2432804 1976 s003 S+ 8:37上午 0:00.00 grep p1.php
will 2697 0.0 0.0 2472792 1284 s002 S 8:37上午 0:00.00 php p1.php
执行结果:
7 6 5 4 3 2 1 0 10 9 8 7 6 5 4 3 2 1 0
不加锁
function writeFileWithoutLock($fp, $i)
{
while ($i >= 0) {
fwrite($fp, $i . ' ');
$i--;
sleep(1);
}
}
$fork = pcntl_fork();
$file = 'test.txt';
$fp = fopen($file, 'ab+');
if ($fork == 0) {
// 子进程
writeFileWithoutLock($fp, 10);
} else {
// 主进程
writeFileWithoutLock($fp, 7);
}
执行结果:
7 10 9 6 8 5 7 4 6 3 5 2 4 1 3 0 2 1 0
MySQL数据库,一天一万条以上的增量,怎么优化
- 优化SQL和索引,考虑存储引擎、数据分布、索引情况、数据库优化策略、锁策略等
- 加缓存,redis或memcache
- 主从复制、主主复制、读写分离
- myql分区表
- 垂直拆分,大系统分为小系统,分布式
- 水平切分,选择合理sharding key,更新表结构,做冗余
参考:
多台MySQL服务器,如何同步数据
如何分库分表
分库
- 主从复制
- 主主复制
- 读写分离
分表
- 垂直拆分
- 水平拆分
写出一种排序算法(要写出代码),并说出优化它的方法
php的错误日志在哪里可以看到?一些框架是如何将所有的错误日志打到某个指定的文件?
通过php.ini可配置是否log以及log文件路径
; Besides displaying errors, PHP can also log errors to locations such as a
; server-specific log, STDERR, or a location specified by the error_log
; directive found below. While errors should not be displayed on productions
; servers they should still be monitored and logging is a great way to do that.
; Default Value: Off
; Development Value: On
; Production Value: On
; http://php.net/log-errors
log_errors = On
...
; Log errors to specified file. PHP's default behavior is to leave this value
; empty.
; http://php.net/error-log
; Example:
error_log = /usr/local/var/log/php_errors.log
; Log errors to syslog (Event Log on Windows).
;error_log = syslog
/*
* ------------------------------------------------------
* Define a custom error handler so we can log PHP errors
* ------------------------------------------------------
*/
set_error_handler('_error_handler');
set_exception_handler('_exception_handler');
register_shutdown_function('_shutdown_handler');
function _shutdown_handler()
{
$last_error = error_get_last();
if (isset($last_error) &&
($last_error['type'] & (E_ERROR | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING)))
{
_error_handler($last_error['type'], $last_error['message'], $last_error['file'], $last_error['line']);
}
}
if ( ! function_exists('_error_handler'))
{
/**
* Error Handler
*
* This is the custom error handler that is declared at the (relative)
* top of CodeIgniter.php. The main reason we use this is to permit
* PHP errors to be logged in our own log files since the user may
* not have access to server logs. Since this function effectively
* intercepts PHP errors, however, we also need to display errors
* based on the current error_reporting level.
* We do that with the use of a PHP error template.
*
* @param int $severity
* @param string $message
* @param string $filepath
* @param int $line
* @return void
*/
function _error_handler($severity, $message, $filepath, $line)
{
$is_error = (((E_ERROR | E_PARSE | E_COMPILE_ERROR | E_CORE_ERROR | E_USER_ERROR) & $severity) === $severity);
// When an error occurred, set the status header to '500 Internal Server Error'
// to indicate to the client something went wrong.
// This can't be done within the $_error->show_php_error method because
// it is only called when the display_errors flag is set (which isn't usually
// the case in a production environment) or when errors are ignored because
// they are above the error_reporting threshold.
if ($is_error)
{
set_status_header(500);
}
// Should we ignore the error? We'll get the current error_reporting
// level and add its bits with the severity bits to find out.
if (($severity & error_reporting()) !== $severity)
{
return;
}
$_error =& load_class('Exceptions', 'core');
$_error->log_exception($severity, $message, $filepath, $line);
// Should we display the error?
if (str_ireplace(array('off', 'none', 'no', 'false', 'null'), '', ini_get('display_errors')))
{
$_error->show_php_error($severity, $message, $filepath, $line);
}
// If the error is fatal, the execution of the script should be stopped because
// errors can't be recovered from. Halting the script conforms with PHP's
// default error handling. See http://www.php.net/manual/en/errorfunc.constants.php
if ($is_error)
{
exit(1); // EXIT_ERROR
}
}
}
/**
* Exception Logger
*
* Logs PHP generated error messages
*
* @param int $severity Log level
* @param string $message Error message
* @param string $filepath File path
* @param int $line Line number
* @return void
*/
public function log_exception($severity, $message, $filepath, $line)
{
$severity = isset($this->levels[$severity]) ? $this->levels[$severity] : $severity;
log_message('error', 'Severity: '.$severity.' --> '.$message.' '.$filepath.' '.$line);
}
if ( ! function_exists('log_message'))
{
/**
* Error Logging Interface
*
* We use this as a simple mechanism to access the logging
* class and send messages to be logged.
*
* @param string the error level: 'error', 'debug' or 'info'
* @param string the error message
* @return void
*/
function log_message($level, $message)
{
static $_log;
if ($_log === NULL)
{
// references cannot be directly assigned to static variables, so we use an array
$_log[0] =& load_class('Log', 'core');
}
$_log[0]->write_log($level, $message);
}
}
Log::write_log() // important
- register handler
- trigger error, shutdow
- get error info
- write log
php中WEB上传文件的原理是什么,如何限制上传文件的大小?
上传文件原理
- 选择文件,点击上传
- 请求发往服务器,php将上传文件的信息保存到$_FILES
- 文件被上传后,默认地会被储存到服务端的默认临时目录中,php.ini可配置
- 验证大小类型等
- 使用copy()函数或者 move_uploaded_file() 函数移动到正式目录
- 如果该文件没有被移动到其它地方也没有被改名,则该文件将在表单请求结束时被删除。
限制上传文件大小
- 配置
php.ini
中的upload_max_filesize
和post_max_size
- 动态检查
$_FILES['userfile']['size']
项
名词解释CGI 、 fastcgi 、php-cgi、php-fpm
CGI
: Common Gateway Interface
一种协议
之所以出现,是为了解决不同服务器软件(Apache、Niginx等)和程序之间直接进行信息交流的不一致性
- 如果程序使用了CGI标准,就称之为CGI程序,
php-cgi
就是一种CGI程序。 - CGI标准定义了许多环境变量,例如uri放在PATH_INFO,GET请求的参数放在QUERY_STRING,POST请求放在标准输入(standard input),程序从环境变量或者标准输入获取数据来生成响应并写入标准输出,服务器软件将其发往客户端。
- 大致流程:user request -> web server(nginx|apache) ->
CGI
缺点:针对每个请求启动一个进程,并初始化环境
Fastcgi
- 一种协议
- Fastcgi用来提高CGI程序性能
php-cgi
- php解释器,CGI程序
- 解析请求,返回结果,不能进程管理
php-fpm
- 实现了
Fastcgi
的程序 - 调度
php-cig
进程
简单图例:
参考
- https://serverfault.com/questions/645755/differences-and-dis-advanages-between-fast-cgi-cgi-mod-php-suphp-php-fpm
- https://en.wikipedia.org/wiki/Common_Gateway_Interface
empty 返回为true的情况,”==”与”===” 的异同
var_dump(empty(''), empty(0), empty(false), empty(null));
var_dump(100 == '100', 100 === '100', 100 === 100); // true false true
var_dump('' == 0, '' === 0); // true false
var_dump(false == null, false === null);// true false
var_dump(10 == true, 10 === true); // tru false
var_dump('12abc' == 12, '12abc' === 12); // true false
如何设置类的自动加载?
SESSION与 COOKIE的区别是什么,请从协议,产生的原因与作用说明(未完)
*为什么要使用cookie ?*http是无状态协议(stateless protocol),客户端与服务器间的交互流程大致是
- 通过DNS将域名解析为ip地址
- HTTP协议生成请求报文
- TCP协议将报文分割成报文段,排序,采用三次握手策略确保每个报文可靠地传递给服务器
- IP协议搜索服务器地址,边中转边传送
- 服务器接收到请求报文,通过TCP重组报文
- 服务器按照HTTP协议处理请求
- 请求发往客户端
- 断开连接
服务器将响应发往客户端之后,并不保存关于上次请求的信息,所以它不能区分前后的请求是否属于同一客户端。因此,在客户端与服务器交互的过程中,需要携带一小段信息,作为当前客户端的唯一标志,通常是session id。
session id在客户端如何保存呢?使用cookie技术,它有以下特点:
- 保存在客户机上
- 通常数据比较小
- 通过key-value形式保存
- 可以设置有效期、作用域等
服务器端将session id设置为cookie,放在响应头,客户端浏览器接收到cookie,保存到客户机(不同浏览器的保存方式不同),下次请求会将cookie放在请求头,服务器解析请求头中的cookie,便知道前后的请求属于同一客户端,因此能够维持会话状态。通常,服务器端需要针对当前会话保存很多信息,有些比较私密,比如用户信息,有些格式比较复杂,这些信息保存在cookie中不合适。
服务器端针对当前会话的信息保存到哪里呢?使用session技术。session通过session id关联用户,并将用户信息存储在服务器端,它有以下特点:
- 关联特定用户的特定会话
- 可设置有效期
- 存储在服务器端,存储方式可以是文件,RDBS,redis或memcache等
传递session id的方式
- URL重写
URL Rewrite
(解决客户端禁用cookie的方案) - Cookie (只有cookie可以持久化存储session id)
- 隐藏表单
hidden input
访问新浪站点的请求头
访问新浪站点www.sina.com的请求头
从 news.sina.com.cn 跳转到 games.sina.com.cn 的请求头
PHP实现n个无序的数组top m(m
PHP 实现有序数组中二分查找某个元素
/**
* @author Qiankun
* @param array $arr
* @param $low
* @param $high
* @param $target
* @return int|null
*/
function binarySearch(array $arr, $low, $high, $target)
{
if (!is_array($arr))
return null;
$mid = (int)($low + ($high - $low) / 2);
if ($target == $arr[$mid])
return $mid;
if ($target > $arr[$mid])
return binarySearch($arr, $mid + 1, $high, $target);
else
return binarySearch($arr, $low, $mid - 1, $target);
}
$sortedArr = range(1, 10000);
foreach ($sortedArr as $val) {
$index = binarySearch($sortedArr, 0, count($sortedArr)-1, $val);
if (is_null($index)) {
echo "Not found \n";
break;
} else
echo $val . "'s index is: " . $index . "\n";
}
PHP的序列化和反序列化函数是?何种场景下使用
serialize()
& unseiralize()
- 将数组或对象序列化成文本保存
- $_SESSION中的值默认被序列化存储
PHP的编码转换函数?编码转换的准则或者注意的地方是什么?
程序代码中修改某些php.ini的配置项
PHP 在进行数据库交互中如何防止sql注入
防SQL注入
- 使用prepare语句(PDO或MySQLi),并将用户传递的查询条件参数化
- 对于需要用户输入动态生成的查询,提前设定whitelist,对用户输入的关键词等信息验证
- 不要手动转义,安全性不如prepare
参考
- https://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php
- http://php.net/manual/zh/security.database.sql-injection.php
- https://phpdelusions.net/sql_injection
有大量的ip和地域数据,如何实现类似ip 138的根据某个ip查处数据
火车票售票系统数据库表设计及程序实现(需要考虑每个用户会购买不同车次的票,同一个车次的票有一定的数量,并发购买时的情况,要求有的功能两个一个购票接口、一个是查询接口)
大数据量高并发、吞吐网站的设计(画示意图配合文字说明)
常见的攻击方式和防御方法
攻击方式
- CSRF:Cross-site Request Forgery,跨站请求伪造
- XSS:Cross Site Scripting,跨站脚本攻击
- DoS和DDoS:Denial of Service,Destribute Denial of Service 拒绝服务和分布式拒绝服务
- SQL注入
跨站请求伪造
工作原理
攻击者发现CSRF漏洞——构造代码——发送给受害人——受害人打开——受害人执行代码——完成攻击
如何防御
- 在客户端页面增加伪随机数,即校验token
- 检查HTTP头中的Referrer字段
- 使用验证码
- 尽量不要在页面的链接中暴露用户隐私信息。
- 对于用户修改删除等操作最好都使用post 操作 。
- 避免全站通用的cookie,严格设置cookie的域。
跨站脚本攻击
工作原理
攻击者发现XSS漏洞——构造代码——发送给受害人——受害人打开——攻击者获取受害人的cookie——完成攻击
合并两个数组有几种方式,试比较它们的异同
请写一个函数来检查用户提交的数据是否为整数(不区分数据类型,可以为二进制、八进制、十进制、十六进制数字)
function isInt($param)
{
$param = strval ($param);
if (false !== strpos ($param, '.'))
return false;
// is hexadecimal ?
if (ctype_xdigit ($param))
return true;
// is binary, decimal, octal?
return filter_var ($param, FILTER_VALIDATE_INT);
}
$tests = [100,1.23,764,'a100f', '123hello','1000010'];
foreach ($tests as $test) {
if (isInt ($test))
echo "{$test} is an integer\n";
else
echo "{$test} is not an integer\n";
}
输出:
100 is an integer
1.23 is not an integer
764 is an integer
a100f is an integer
123hello is not an integer
1000010 is an integer
PHP的strtolower()和strtoupper()函数在安装非中文系统的服务器下可能会导致将汉字转换为乱码,请写两个替代的函数实现兼容Unicode文字的字符串大小写转换
PHP的is_writeable()函数存在Bug,无法准确判断一个目录/文件是否可写,请写一个函数来判断目录/文件是否绝对可写
PHP的chmod()函数存在Bug,无法保证设置成功,请写一个函数在指定路径下创建一个目录/文件并确保可以正确设置权限掩码
PHP处理上传文件信息数组中的文件类型$_FILES[‘type’]由客户端浏览器提供,有可能是黑客伪造的信息,请写一个函数来确保用户上传的图像文件类型真实可靠
function check($type = 'jpg', $filePath)
{
if (!file_exists ($filePath))
return false;
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $filePath);
finfo_close ($finfo);
$extensions = [
'image/bmp' => 'bmp',
'image/x-ms-bmp' => 'bmp',
'image/cgm' => 'cgm',
'image/g3fax' => 'g3',
'image/gif' => 'gif',
'image/ief' => 'ief',
'image/jpeg' => 'jpeg',
'image/pjpeg' => 'jpeg',
'image/ktx' => 'ktx',
'image/png' => 'png',
'image/prs.btif' => 'btif',
'image/sgi' => 'sgi',
'image/svg+xml' => 'svg',
'image/tiff' => 'tiff',
'image/vnd.adobe.photoshop' => 'psd',
'image/vnd.dece.graphic' => 'uvi',
'image/vnd.dvb.subtitle' => 'sub',
'image/vnd.djvu' => 'djvu',
'image/vnd.dwg' => 'dwg',
'image/vnd.dxf' => 'dxf',
'image/vnd.fastbidsheet' => 'fbs',
'image/vnd.fpx' => 'fpx',
'image/vnd.fst' => 'fst',
'image/vnd.fujixerox.edmics-mmr' => 'mmr',
'image/vnd.fujixerox.edmics-rlc' => 'rlc',
'image/vnd.ms-modi' => 'mdi',
'image/vnd.ms-photo' => 'wdp',
'image/vnd.net-fpx' => 'npx',
'image/vnd.wap.wbmp' => 'wbmp',
'image/vnd.xiff' => 'xif',
'image/webp' => 'webp',
'image/x-3ds' => '3ds',
'image/x-cmu-raster' => 'ras',
'image/x-cmx' => 'cmx',
'image/x-freehand' => 'fh',
'image/x-icon' => 'ico',
'image/x-mrsid-image' => 'sid',
'image/x-pcx' => 'pcx',
'image/x-pict' => 'pic',
'image/x-portable-anymap' => 'pnm',
'image/x-portable-bitmap' => 'pbm',
'image/x-portable-graymap' => 'pgm',
'image/x-portable-pixmap' => 'ppm',
'image/x-rgb' => 'rgb',
'image/x-tga' => 'tga',
'image/x-xbitmap' => 'xbm',
'image/x-xpixmap' => 'xpm',
'image/x-xwindowdump' => 'xwd'
];
return (isset($extensions[$mimeType]) && $extensions[$mimeType] == $type) ? true : false;
}
if (check ('jpeg', 'test.jpg'))
echo 'correct';
(未完)PHP通过对数据的URL编码来实现与Javascript的数据交互,但是对于部分特殊字符的编解码与Javascript的规则不尽相同,请具体说明这种差异,并针对UTF-8字符集的数据,写出PHP的编解码函数和Javascript的编解码函数,确保PHP编码数据可以被Javascript正确解码、Javascript编码的数据可以被PHP正确解码
具体差异(???)
<?php
// encode in php and decode in javascript
$url = 'https://www.google.co.id/logos/doodles/2017/olaudah-equianos-272nd-birthday-5190660549246976.2-s.png';
$encoded = rawurlencode ($url);
echo 'Original url is: ' . $url . "<br />";
echo 'Encoded url is: ' . $encoded . "<br />";
?>
<input id="encoded" type="hidden" value="<?=$encoded?>">
<script type="text/javascript">
var encoded = document.getElementById('encoded').value;
document.write("Decoded url is: " + decodeURIComponent(encoded));
</script>
试阐述Memcache的key多节点分布的算法?当任一节点出现故障时PHP的Memcache客户端将如何处置?如何确保Memcache数据读写操作的原子性?
如何实现PHP的安全最大化?怎样避免SQL注入漏洞和XSS跨站脚本攻击漏洞?
请设计一个数据结构可以实现无限级子菜单的树型菜单功能并提供菜单生成算法,用UML描述设计并写出相关PHP代码
参考
- http://www.freebuf.com/articles/web/55965.html
- https://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html
- http://www.cnblogs.com/shytong/p/5308667.html
- https://zh.wikipedia.org/zh-hans/%E8%B7%A8%E7%AB%99%E8%AF%B7%E6%B1%82%E4%BC%AA%E9%80%A0
参考链接
- 如何面试 PHP 工程师?
PHP面试题集PHP经典面试题汇总新浪面试题及其完整答案- 新浪PHP面试题
- 百度面试题一
- 百度面试题二
- 腾讯PHP面试题