关于ajax的问题(整理回答,发布正确的代码,csrf)

在这里把我遇到的ajax问题和大家的回答整理总结一下, 刚学CI, 
可能有错误
,希望指正。

如果你有以下问题,可能会得到帮助:

1. 跨域访问错误

2. csrf保护开启后ajax出现错误

3. gZip开启后出现ajax错误

测试环境

Ubuntu: firefox, chrome

windows XP: IE, 360浏览器的IE8

1. 跨域访问

(下面的问题经常出现在你载入ajax视图和处理ajax请求是同一个控制器时,是特殊情况,

但因为这是我遇到的第一个问题,
而且折磨了我很久,所以还是写出来了,希望别人能避开这个错误)

(1)当ajax的请求地址和控制器处理程序的地址不一致时会出现错误。

如 ajax在域名‘
www.444.com
‘的视图里, 请求的是 ‘
www.333.com
/ci/index.php/test/ajax‘ ,

则会出现跨域访问错误,我的提示是
 301 Moved Permanently

(2) localhost和127.0.0.1是不同的域

解释:

这个是javascript的安全限制,不能跨域。

(感谢 huboo82的回答)

localhost也叫local ,正确的解释是:本地服务器

127.0.0.1在windows等系统的正确解释是:本机地址(本机服务器)

localhot(local)是不经网卡传输
!这点很重要,它不受网络防火墙和网卡相关的的限制。

127.0.0.1是通过网卡传输,依赖网卡,并受到网络防火墙和网卡相关的限制。

(感谢credochen的回答)

(3) www.ddd.com 和 ddd.com 是不同的域。

解释:

如果ajax请求的地址和控制器的地址里www不一致,则出错.

(不知道是不是我电脑的错误,我在视图 a.php请求的是 "www.ddd.com/ci/index.php/test/ajax", 如果我在url用 “ddd.com/ci/index.php/test”控制器载入视图,然后用同一个控制器处理ajax请求就出错,加上www就没有错。)

(4) ajax请求如果是完整路径,则加上"http://"
,不然Codeigniter会自动在你的地址前面

加上默认路径变成 
http://www.ddd.com/ci/index.php/test/
www.ddd.com/ci/index.php

而这可能不是你的本意

我的解决方法: (不是很好,但是有用)

1)载入视图的和处理ajax请求的分成不同的控制器,
这样ajax的请求就不用担心与调用的,

控制器地址不一样.

2)如果你把调用ajax视图和处理请求的都放到同一个控制器文件里的话.

PHP
复制代码

var body 
= $
(
"body"
)
;

var baseUrl 
= body
.context
.baseURI
;

复制代码

context.baseURI 
会得到载入本视图的地址,这样就能和服务其上的地址一致,避免一些错误,

但这个没有把所有情况考虑进去,你需要自己对这个地址设定一些条件检查。

2.csrf 保护的问题

config里设置 $config[‘csrf_protection‘] = TRUE;  会对post进行 csrf保护,

他会对用户提交的数据进行检查,可以提高安全,建议开启。当然会引发一些问题。

(1)简单的说就是你提交的数据中如果没有特定的值给控制器,就回出错。

-----------------------------------------------------------------

详细的解释: (
这里可以看原帖

感谢c361239752的回答

最近研究CI源码,正好看到CSRF保护,原理是这样的:在config中设置了开始CSRF保护,用form生成表单会生成hidden的一段HASH值,这段HASH会被写入到cookies中源码如下:
setcookie($this->_csrf_cookie_name, $this->_csrf_hash, $expire, config_item(‘cookie_path‘), config_item(‘cookie_domain‘), $secure_cookie);
其中cookie_domain作用域是config中设定的,提交POST后会判断post过来的token和cookies中的token是否存在,再判断这两个值是否相等,否则显示错误页面,判断完后立即unset($_POST[$this->_csrf_token_name]);unset($_COOKIE[$this->_csrf_cookie_name]);以避免污染$_POST数据

-------------------------------------------------------------------

不要被这个解释给吓倒了,其实你要做的只是把一个变量加到你的ajax的提交的数据里,

这个变量定义在你的 $config[‘csrf_token_name‘] = ‘csrf_test_name‘;

这里主要提交的数据是 csrf_test_name的值,Codeigniter会自动添加到Cookie里.

那如何得到哪个变量和值?

这个会返回你要的值

<?php echo $this->security->get_csrf_hash(); ?>

这个会返回你要传递的变量名(就是你设置在
$config[‘csrf_token_name‘]

<?php echo $this->security->get_csrf_token_name(); ?>

给个实例代码? (我们都喜欢具体的实例代码不是吗? 

)

PHP
复制代码

$.ajax({

type: "
OST",

// 这里是你的请求地址

url: "www.ddd.com/ci/index.php/test/ajax",

data: "name="+cv+‘&‘+"
<?php 
echo 
$this
->
security
->
get_csrf_token_name
(
)

?>"+‘=‘+"
<?php 
echo 
$this
->
security
->
get_csrf_hash
(
)

?>",

success: function(msg){

mydiv.html(msg).show();

},

error: function() {

alert("ajax error")

;}

});

复制代码

(2) 表单提交时出错

如果你开启了csrf,然后直接用纯 <from ..></form>格式提交表单就会出错.原因同上

解决方法:

1)用Codeigniter的 form_open() 函数,codeigniter会自动把验证代码插入到视图表单里,然后隐藏并

跟你的数据一起提交。(推荐)

2)用上面的方法获得数据,然后提交.

相关资料:

http://blog.hsin.tw/2011/codeigniter-csrf-protection-form-ajax/

这个博客文章的解决方法很好,可惜代码有错误,不过还是值得参考(我就是从这里得到帮助,解决了问题)

http://codeigniter.com/forums/viewthread/163976/

在这里我找到了解决方法的代码.

3. gZip压缩开启

如果你设置了$config[‘compress_output‘] = TRUE; 不能在任何控制器里使用 echo

因为如果你在控制器用echo输出的方法返回ajax数据,就回出现编码错误。

解决方法:
1. (推荐)
$data = "your ajax return data";
$this->output->set_output($data); (推荐) 
2. $this->load->view(‘data‘); (会把视图内容传输给客户端)

最后让我们贴出激动人心的完整的美丽的强大的......实例代码,用于参考

(我在Ubuntu的firefox和chrome,还有xp里的IE里测试过,不保证其他浏览器里也正确

我使用了jQuery, 请确保jQuery包含了进来,当然你也可以改成纯js.)

视图. ajax.php

HTML
复制代码

<!DOCTYPE HTML>

<html lang="en">

<head>

<script type="text/javascript"    src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

<script type="text/javascript">

$(document).ready(function() {

var mydiv = $("#myDiv");

function swapContent(cv) {

// ajax请求时的等待图片可以写在这里

mydiv.html("
ut animated .gif here").show();

// 因为我调用这个视图的和处理这个ajax的控制器是同一个,所以

// 可能会出现跨域错误

var u = "http://127.0.0.1/ci/index.php/test/ajax";

$.ajax({

type: "
OST",

url: u,

data: "name="+cv+‘
&‘+"<?php echo $this->security->get_csrf_token_name(); ?>"+‘=‘+"
<?php echo $this->security->get_csrf_hash(); ?>",

success: function(msg){

mydiv.html(msg).show();

},

error: function() {alert("ajax error");}

});

}

$("#c1").click(function() {

swapContent("d1");

});

$("#c2").click(function() {

swapContent("d2");

});

$("#c3").click(function() {

swapContent("d3");

});

});

</script>

<meta charset="UTF-8">

<title></title>

</head>

<body>

<a id ="c1" href="#" >Content1
</a>

<a id = "c2" href="#" >Content2
</a>

<a id = "c3" href="#" >Content3
</a>

<div id="myDiv">My default content
</div>

</body>

</html>

复制代码

控制器 test.php

PHP
复制代码

<?php

class Test 
extends CI_Controller 
{

public 
function __construct
(
)
{

parent
::__construct
(
)
;

}

public 
function index
(
)

{

$this
->
load
->
view
(
‘ajax‘
)
;

}

function ajax
(
)

{

$name 

$this
->
input
->
post
(
‘name‘
)
;

$this
->
output
->
set_output
(
‘server get data: ‘
.
$name
)
;

}

}

复制代码

(全文完)

:wq!

时间: 2024-11-13 15:35:06

关于ajax的问题(整理回答,发布正确的代码,csrf)的相关文章

ajax验证表单元素规范正确与否 ajax展示加载数据库数据 ajax三级联动

一.ajax验证表单元素规范正确与否 以用ajax来验证用户名是否被占用为例 1创建表单元素<input type="text" id="t"> 2在js中用keyup事件来进行操作 3创建ajax格式和内容:格式: $.ajax({ url:"哪一个服务端处理器", data:{"自己起名",所需要传给处理器的数据}, type:"post", dataType:"json"

Touch事件or手机卫士面试题整理回答(二)

Touch事件or手机卫士面试题整理回答(二) 自定义控件 1. Touch事件的传递机制 顶级View->父View->子View,不处理逆向返回 OnInterceptTouchEvent(),返回值控制Touch是否向下传递. true中断事件,false不中断事件. onTouchEvent() 返回值决定否处理事件.True消耗事件,False不处理事件向上传递. 2. 轮播动画的实现原理 ViewPage和TextView组合实现图片和标题的效果 ViewPage设置setOnPa

JavaScript必备:Google发布的JS代码规范(转)

[翻译]关于Google发布的JS代码规范,你需要了解什么? 翻译 | WhiteYin 译文 | https://github.com/WhiteYin/translation/issues/10 Google为了那些还不熟悉代码规范的人发布了一个JS代码规范.其中列出了编写简洁易懂的代码所应该做的最佳实践. 代码规范并不是一种编写正确JavaScript代码的规则,而是为了保持源代码编写模式一致的一种选择.对于JavaScript语言尤其如此,因为它灵活并且约束较少,允许开发者使用许多不同的

前端部署ant+yuicompressor文件压缩+获取版本号+SSH发布(部分代码)

文件压缩: <apply executable="java" parallel="false" failonerror="true" dest="../../release/publish/ecshop" append="false" force="true"> <fileset dir="../../release/publish/ecshop"&

Head First Python(如何向PYPI发布你的代码)学习笔记

Head  First  Python(如何向PYPI发布你的代码) 当我们编写好的一个完美的python程序或者一个好的项目程序时,那时作为程序猿的我们是如何的激动啊,在那激动的时刻如何与他人分享我们胜利的果实呢?看这里~哈哈 为了共享这个模块,需要将它发布出去,在python中,所谓发布(distribution)是指一个文件集合,将这些文件联合到一起允许你构建,打包和发布你的模块,一旦发布,就可以 把模块先安装到你的本地python上,还有就是可以把你的代码上传到PYPI与全世界共享你的代

JS验证邮箱格式是否正确 实例代码

如何用js验证邮箱格式是否正确?分享一个例子.代码: /* *验证邮箱格式是否正确 *参数strEmail,需要验证的邮箱 */ function chkEmail(strEmail) { if (!/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(strEmail)) { return false; } else { return true; } } 您可能感兴趣的文章: js正则表达式判断邮箱格式是否正确 js验证邮箱格式 js验证em

腾讯发布2017年代码报告

腾讯发布2017年代码报告,对过去一年研发数据进行了统计,涵盖代码.开发者.语言等基础数据. 扫描下方二维码或点击链接查看↓↓↓ 链接:http://m.code.tencent.com/report/2017company?ADTAG=tx.report.qr_teg 原文地址:http://blog.51cto.com/13591395/2083310

实现一个简单的订阅与发布模式的代码块,和redux

/** * Created by Mrzou on 2018/3/11. */ //实现简单的订阅与发布模式的代码块export function pattern() { let currentListeners = [] function subscribe(type, listener) { if ((typeof listener !== 'function') || (typeof listener !== 'string')) { throw new Error('参数类型错误') }

jquery ajax 后台响应成功,返回正确json但不执行success方法,执行error的问题

昨天被这问题卡了好几个小时.查看http状态码:是200.而且返回了预想的json字符串.但执行的是error方法,不执行success方法.在网上查了一下,才发现是后台页面返回的json字符串格式不对,我的错误是冒号“:”写成了逗号“,”.就会出现ajax前端的js代码直接调用error中的方法这样的问题. 可以去json在线验证网站 看下自己的json串是否正确,如果是用json工具包生成的json串是没有问题的.