Path 和 URL 浅谈

本文深入解析了URL与文件路径在Web开发中的应用与区别,包括它们如何在不同系统间进行转换,如何使用相对URL,以及如何进行URL编码以确保数据安全与准确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 通常,path是一个文件系统概念,是某一文件在文件系统中的指针:
C:\xampp\htdocs\index.php 这是windows系统中的写法,其实windows支持斜线(/)和反斜线(\),Unix/Linux只支持(/)。因为(\)会被误认为转义字符, 建议一概使用(/)。另外,windows文件路径中可以有空格C:/xampp/htdocs/images//avatar.jpg是合法的,但在 unix/linux系统中不合法。为了写出“可移植的”php程序,建议统一使用php文件系统扩展预定义常 量:DIRECTORY_SEPARATOR,PATH_SEPARATOR

2. url是http协议下的概念,是互联网上任一资源的指针,所以它是相对主机而言的地址,可以是本站上的资源,也可以是其他主机上的资源。http协议规定,所有的web request都以url的格式给出:
http://localhost/images/user/007/avatar.jpg对应的文件系统路径是:
C:/xampp/htdocs/images/user/007/avatar.jpg
其实web 服务器也接受file path作为请求,只不过会转换协议:file:///C:/xampp/htdocs/images/user/007/avatar.jpg

(注意:因为file path和url都可以定位一个文件,有的文件操作函数比如fopen接受多协议参数:file path,或http url,有的函数只接受path,比如is_file,file_exists)

3. http协议对url的句法做了详细规定:
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
所以上例url中,<path>段就是/images/user/007/avatar.jpg,web
服务器(apache等)会将这个path映射到文件系统中的file path中去,以获取C:/xampp/htdocs/images/user/007/avatar.jpg

4. 相对url。只有完整的(绝对)url才可以定位一个资源,但如果(显式地或暗含地)指定了一个参考点,就可以使用相对url。相对url是相对当前(或指定)url的url:
比如,在http://locaohost/user/index.php这一脚本中,你可以使用
<img src='http://wyllife.blog.163.com/blog/images/user/007/avatar.jpg' />这一相对url来定位资源,它实际把当前资源的绝对url作为了参考,使用了相对url,得到完整的http://localhost/user/images/user/007/avatar.jpg
相对url不能以/开头,因为凡是以/开头的url都会被解释为基址,比如
<img src='/images/user/007/avatar.jpg />会被解释为:
http://localhost/images/user/007/avatar.jpg

5. url编码问题(涉及到urlencode,rawurlencode,htmlentities,htmlspecialchars等函数的使用)
url 是用户的请求格式,它来自客户的地址栏输入或点击或作为页面构成的资源定位(如img,object),开发人员无法控制客户的输入,但你提供的点击是可 以掌控的。对url编码,是为了服务器获得准确(符合用户本意)和安全(符合服务器安全规范)的url,以提供有效的服务。
url可以用任何字符 构成,但只能以ascii码字符集来传输,所以url中的任何非ascii字符都需要进行转码才能被服务器接受。ascii字符集中一部分具有特殊含义和 功能的字符被称为reserved characters. 要在url中使用保留字符(literal use)也需要做转码。
php函数 rawurlencode/urlencode会将字符串中所有除[a-zA-z.-_]之外的字符进行转码,中文也会被转码(注意部分浏览器会对 encoded的url自动进行解码)。这个问题和html实体问题类似:html文本中可以出现任何字符,但是有些字符对html而言是有特殊含义的 (比如<),有些会被特殊处理(比如连续空格),要使用这些字符,必须使用html 实体,这样导致所有的字符都有其urlencode码(&#number格式的,只有部分有&nbsp;这样的名字),也有其html实 体码。php函数htmlspecialchars和htmlentities的功能就是将字符串中的特殊字符都转换为对应的html实体,以避免造成冲 突和混乱。

(另:表单数据提交是经过html entities转码和url 转码双重处理的,比如input里面输入的"美 女",实际提交给服务器的是%26%2332654%3B+%26%2322899%3B)

/** * 搜索列表 */ public function lists() { $param = input('param.'); $users = session('?users') ? session('users') : []; $users_id = !empty($users['users_id']) ? intval($users['users_id']) : 0; $admin_id = !empty($users['admin_id']) ? intval($users['admin_id']) : 0; $nowTime = getTime(); /*记录搜索词*/ if (!isset($param['keywords'])) { die('标签调用错误:缺少属性 name="keywords",请查看标签教程修正 <a href="https://www.eyoucms.com/plus/view.php?aid=521" target="_blank">前往查看</a>'); } $word = $this->request->param('keywords'); if(empty($word)){ $this->error(foreign_lang('system15', $this->home_lang)); } $page = $this->request->param('page'); if(!empty($word) && 2 > $page) { $word_decode = htmlspecialchars_decode($word); $searchConf = tpCache('search'); if (!isset($searchConf['search_tabu_words'])) { $searchConf['search_tabu_words'] = ['<','>','"',';',',','@','&','#','\\','*']; } else { $searchConf['search_tabu_words'] = explode(PHP_EOL, $searchConf['search_tabu_words']); } /*前台禁止搜索开始*/ if (!empty($searchConf['search_tabu_words'])) { foreach ($searchConf['search_tabu_words'] as $key => $val) { if (strstr($word_decode, $val)) { $msg = sprintf(foreign_lang('system13', $this->home_lang), $val); $this->error($msg); } } } /*if (is_dir('./weapp/Wordfilter/')) { $wordfilterRow = Db::name('weapp')->where(['code'=>'Wordfilter', 'status'=>1])->find(); if(!empty($wordfilterRow['data'])){ $wordfilterRow['data'] = json_decode($wordfilterRow['data'], true); if ($wordfilterRow['data']['search'] == 3){ $wordfilter = Db::name('weapp_wordfilter')->where(['title'=>$word, 'status'=>1])->find(); if(!empty($wordfilter)){ $this->error('包含敏感关键词,禁止搜索!'); } } } }*/ /*前台禁止搜索结束*/ // 如果tag标签有,默认跳到tag列表页 /*$tagInfo = Db::name('tagindex') ->alias('a') ->field('a.id AS tagid') ->join('taglist b','a.id=b.tid','left') ->where(['a.tag'=>$word,'b.arcrank'=>['egt',0]]) ->find(); if (!empty($tagInfo)) { $city_switch_on = config('city_switch_on'); $domain = preg_replace('/^(http(s)?:)?(\/\/)?([^\/\:]*)(.*)$/i', '${1}${3}${4}', tpCache('web.web_basehost')); if (empty($city_switch_on)) { $tagurl = tagurl('home/Tags/lists', array('tagid'=>$tagInfo['tagid'])); } else { $tagurl = tagurl('home/Tags/lists', array('tagid'=>$tagInfo['tagid']), true, $domain); } $this->redirect($tagurl); exit; }*/ $word = addslashes($word); $method = input('param.method/d'); if (!empty($method)) { /*搜索频率限制 start*/ if (!isset($searchConf['search_second'])) { $searchConf['search_second'] = 60; } if (!isset($searchConf['search_maxnum'])) { $searchConf['search_maxnum'] = 5; } if (!isset($searchConf['search_locking'])) { $searchConf['search_locking'] = 120; } if (empty($admin_id) && 0 < $searchConf['search_second']) { $where = []; if (!empty($users_id)) { $where['users_id'] = $users_id; } else { $where['ip'] = clientIP(); } $where2 = [ 'update_time' => ['gt', $nowTime - $searchConf['search_second']], ]; $searchTotal = Db::name('search_word')->where($where)->where($where2)->count(); $lockingInfo = Db::name('search_locking')->where($where)->find(); if ($searchTotal >= intval($searchConf['search_maxnum'])) { if (empty($lockingInfo)) { $lockingInfo = [ 'users_id' => $users_id, 'ip' => clientIP(), 'locking_time' => $nowTime, 'add_time' => $nowTime, 'update_time' => $nowTime, ]; $insertId = Db::name('search_locking')->insertGetId($lockingInfo); $lockingInfo['id'] = $insertId; } else { if (($lockingInfo['locking_time'] + $searchConf['search_locking']) < $nowTime) { Db::name('search_locking')->where(['id'=>$lockingInfo['id']])->update([ 'locking_time' => $nowTime, 'update_time' => $nowTime, ]); $lockingInfo['locking_time'] = $nowTime; } } } if (!empty($lockingInfo)) { $locking_time = !empty($lockingInfo['locking_time']) ? $lockingInfo['locking_time'] : 0; $surplus_time = $locking_time + $searchConf['search_locking'] - $nowTime; if ($surplus_time > 0) { $minute = ceil($surplus_time/60); $msg = sprintf(foreign_lang('system14', $this->home_lang), $minute); $this->error($msg, null, [], $surplus_time); } } } /*搜索频率限制 end*/ /*记录搜索词*/ $row = $this->searchword_db->field('id')->where(['word'=>$word, 'lang'=>$this->home_lang])->find(); if(empty($row)) { $this->searchword_db->insert([ 'word' => $word, 'sort_order' => 100, 'users_id' => $users_id, 'ip' => clientIP(), 'lang' => $this->home_lang, 'add_time' => $nowTime, 'update_time' => $nowTime, ]); }else{ $this->searchword_db->where(['id'=>$row['id']])->update([ 'searchNum' => Db::raw('searchNum+1'), 'users_id' => $users_id, 'ip' => clientIP(), 'update_time' => $nowTime, ]); } } } /*--end*/ $result = $param; !isset($result['keywords']) && $result['keywords'] = ''; $eyou = array( 'field' => $result, ); $this->eyou = array_merge($this->eyou, $eyou); $this->assign('eyou', $this->eyou); /*模板文件*/ $viewfile = 'lists_search'; $channelid = input('param.channelid/d'); if (!empty($channelid)) { $viewfilepath = TEMPLATE_PATH.$this->theme_style_path.DS.$viewfile."_{$channelid}.".$this->view_suffix; if (file_exists($viewfilepath)) { $viewfile .= "_{$channelid}"; } } /*--end*/ if (config('city_switch_on') && !empty($this->home_site)) { // 多站点内置模板文件名 $viewfilepath = TEMPLATE_PATH.$this->theme_style_path.DS.$this->home_site; $viewfilepath2 = TEMPLATE_PATH.$this->theme_style_path.DS.'city'.DS.$this->home_site; if (!empty($this->eyou['global']['site_template'])) { if (file_exists($viewfilepath2)) { $viewfile = "city/{$this->home_site}/{$viewfile}"; } else if (file_exists($viewfilepath)) { $viewfile = "{$this->home_site}/{$viewfile}"; } } } else if (config('lang_switch_on') && !empty($this->home_lang)) { // 多语言内置模板文件名 $viewfilepath = TEMPLATE_PATH.$this->theme_style_path.DS.$viewfile."_{$this->home_lang}.".$this->view_suffix; if (file_exists($viewfilepath)) { $viewfile .= "_{$this->home_lang}"; } } return $this->fetch(":{$viewfile}"); } 检测sql注入利用链
最新发布
07-30
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值