资讯专栏INFORMATION COLUMN

部门和人员全部实现无刷新并结合Csrf验证所遇问题

Zhuxy / 1720人阅读

摘要:根据文章的标题,大家应该看出来了,我在部门和人员这一模块当中就用了无刷新的技术,一并结合自带的验证。需求分析做一个部门和人员模块全部使用无刷新技术开发。一大模块全部实现无刷新,有些方法代码量会很大,得把握好它们之间的相关性和其它互不影响性。

前言

Ajax+PHP实现动态无刷新技术应用及其广泛,因为它有着可动态的实现WEB页面局部刷新,减轻服务器端负担,按需取数据,能带来更好的用户体验的优势。主要适用的场景像一些表单驱动的交互,普通的文本输入提示和自动完成,投票yes/no等无关痛痒的场景等等。根据文章的标题,大家应该看出来了,我在“部门和人员”这一模块当中就用了无刷新的技术,一并结合Yii2自带的Csrf验证。在这么使用的时候,我遇到了一些问题,也想出了一些解决方式,今天花了点时间整理一下,分享了。

需求分析

1、做一个部门和人员模块全部使用Aajx无刷新技术开发。
2、要求使用Yii2自带的Csrf验证。

效果图

部门和人员模块效果

Csrf验证

代码分析

结合需求,在点击的按钮上全部加上onClick点击事件,然后function事件的方法通过Ajax把数据传到控制器处理,返回进行局部刷新页面,查看结果是否正确,实现思路大致就这样。这么说可能还有人迷糊,下面我附上代码,因代码量太大,所以我只附关键部分。

以添加员工为例:

1、视图部分

点击添加员工按钮,在添加员工按钮上定义个onClick="AddUser()"事件,因为我用的是a标签,所以为了避免双重点击跳转,这里我把a标签里的href设为“javascript:void(0);”禁止跳转。

</>复制代码

  1. 添加员工

点击提交表单按钮,通过Ajax提交。注意这里我使用的是Button,而不是submitButton,使用submitButton无法实现无刷新。

</>复制代码

  1. "btn btn-primary","onClick"=>"UUpdate1()"]) ?>

2、JS部分。

我分成两步走,第一步是点击添加展示视图页面,第二部分是添加部门提交表单验证,返回局部刷新页面。

</>复制代码

  1. 第一步:
  2. //列表添加员工
  3. function AddUser(){
  4. $.ajax({
  5. type : "post",
  6. url : "/department/tree",
  7. dataType : "text",
  8. data : {"AddUser":"AddUser"}, //固定参数,区分用
  9. success : function(data){
  10. $("#href_data").html(data);
  11. }
  12. });
  13. }

</>复制代码

  1. 第二步:
  2. //列表添加员工提交表单验证
  3. function AddUser1(){
  4. var id=$("#current_dep").val();
  5. var company_id=$("#current_com").val();
  6. var parent_id=$("#user-parent_id").val();
  7. var t_nickname=$("#user-t_nickname").val();
  8. var t_realname=$("#user-t_realname").val();
  9. var t_mobile=$("#user-t_mobile").val();
  10. var t_email=$("#user-t_email").val();
  11. //获取选中部门
  12. var arr = document.getElementsByName("department_ids[]");
  13. var arrLen = arr.length;
  14. var chk = [];
  15. var chkPoint = 0;
  16. for (var i = 0; i < arrLen; i ++) {
  17. if(arr[i].checked == true){
  18. chk[chkPoint] = arr[i].value;
  19. chkPoint ++;
  20. }
  21. }
  22. //获取选中职位
  23. var posit = document.getElementsByName("UserProfile[position][]");
  24. var arrlen = posit.length;
  25. var position = [];
  26. var chkpoint = 0;
  27. for (var i = 0; i < arrlen; i ++) {
  28. if(posit[i].checked == true){
  29. position[chkpoint] = posit[i].value;
  30. chkpoint ++;
  31. }
  32. }
  33. //昵称,真实姓名,邮箱同时存在才能提交表单
  34. if(t_nickname && t_realname && t_email){
  35. $.ajax({
  36. type : "post",
  37. url : "/department/tree",
  38. dataType : "text",
  39. data : {
  40. "UId":id,
  41. "UCompany_id":company_id,
  42. "SEdit":"SEdit",
  43. "add_user":"add_user",
  44. "User[parent_id]":parent_id,
  45. "User[t_nickname]":t_nickname,
  46. "User[t_realname]":t_realname,
  47. "User[t_mobile]":t_mobile,
  48. "User[t_email]":t_email,
  49. "department_ids":chk,
  50. "UserProfile[position]":position,
  51. "_csrf":"request->getCsrfToken (); ?>"
  52. },
  53. success : function(data){
  54. $("#href_data").html(data);
  55. }
  56. });
  57. }else{
  58. $.ajax({
  59. type : "post",
  60. url : "/department/tree",
  61. dataType : "text",
  62. data : {"UId":id,"UCompany_id":company_id,"SEdit":"SEdit","add_user":"add_user","User[t_nickname]":t_nickname,"User[t_realname]":t_realname,"User[t_email]":t_email,"User[t_mobile]":t_mobile},
  63. success : function(data){
  64. $("#href_data").html(data);
  65. }
  66. });
  67. }
  68. }

注释:三个url都是一样的,这就是Ajax的特别之处,不管页面数据怎么变化,url地址还是一样的。

3、PHP部分。

</>复制代码

  1. 列表-添加员工展示视图
  2. if(!empty($post["AddUser"])){
  3. $Data=$this->actionTreeUpdate("",$user1->company_id,""); //获取员工,员工详细信息,部门实例化的model
  4. return $this->renderPartial("tree_update", [
  5. "model" => $Data["model"],
  6. "model_1" => $Data["model_"],
  7. "departar"=>$Data["departar"],
  8. "positionar"=>$Data["positionar"],
  9. "users" => $Data["users"],
  10. "UId"=>"", //添加不需要传
  11. "UCompany_id"=>"", //添加不需要传
  12. "add_user"=>"add_user"
  13. ]);
  14. }

</>复制代码

  1. department里的tree方法主要代码,验证保存数据在这里
  2. if(!empty($post["SEdit"])){
  3. $UId=$post["UId"];
  4. $UCompany_id=$post["UCompany_id"];
  5. $SEdit=$post["SEdit"];
  6. $add_user=!empty($post["add_user"])?$post["add_user"]:"";
  7. unset($post["SEdit"],$post["UId"],$post["UCompany_id"],$post["add_user"]);
  8. $Data=$this->actionTreeUpdate($UId,$UCompany_id,$post);
  9. $class = $this->userModels;
  10. $Class_= $this->UserProfile;
  11. //判断是否为添加员工
  12. if(!empty($add_user)){
  13. $UId=0;
  14. }
  15. $model_2 = $class::findIdentity($UId);
  16. $model_3=$Class_::findOne($UId);
  17. //列表-添加员工
  18. $t_id1="";
  19. $t_id=!empty($model_2->attributes["t_id"])?$model_2->attributes["t_id"]:"";
  20. if(empty($model_2)){
  21. $model_2 = new $class;
  22. $post["_csrf"]=Yii::$app->request->getCsrfToken();
  23. $depart=!empty($post["department_ids"])?$post["department_ids"]:array();
  24. $model_2->parent_id=!empty($post["User"]["parent_id"])?$post["User"]["parent_id"]:"";
  25. if($depart)
  26. {
  27. $model_2->department_id1=!empty($depart[0])?$depart[0]:0;
  28. $model_2->department_id2=!empty($depart[1])?$depart[1]:0;
  29. $model_2->department_id3=!empty($depart[2])?$depart[2]:0;
  30. $model_2->department_ids=join(",",$depart);
  31. }else{
  32. $model_2->department_ids="";
  33. }
  34. $model_2->t_password=base64_encode($user1->t_password);
  35. $model_2->t_state=0;
  36. $model_2->t_status=1;
  37. $model_2->company_id= $user1->company_id;
  38. if($model_2->load($post) && $model_2->save()){
  39. //插入返回员工id
  40. $t_id1=$model_2->attributes["t_id"];
  41. $Data="success";
  42. }
  43. }
  44. //验证通过,选择职位后保存
  45. if($model_2->load($post) && $model_2->validate() && !empty($post["UserProfile"]["position"])){
  46. $Data="success";
  47. }
  48. if($model_2->load($post) && $model_2->validate() && $Data=="success"){
  49. if(empty($model_3) && !empty($t_id1)){
  50. $model_3 = new $Class_;
  51. $model_3->uid=$t_id1;
  52. }
  53. //保存职位
  54. if(!empty($post["UserProfile"]["position"]) && $model_3->load($post))
  55. {
  56. $posar=!empty($post["UserProfile"]["position"])?$post["UserProfile"]["position"]:array();
  57. if($posar)
  58. {
  59. $model_3->position_id1=!empty($posar[0])?$posar[0]:0;
  60. $model_3->position_id2=!empty($posar[1])?$posar[1]:0;
  61. $model_3->position_id3=!empty($posar[2])?$posar[2]:0;
  62. $model_3->position_ids=$posar?join(",",$posar):"";
  63. $model_3->position=Position::getpos_name($posar);
  64. }else{
  65. $model_3->position_id1="";
  66. }
  67. $model_3->save();
  68. }else{
  69. $posar=!empty($post["UserProfile"]["position"])?$post["UserProfile"]["position"]:array();
  70. if(empty($posar)){
  71. //判断个人详细信息表是否有值,有值直接替换,无值重新实例化
  72. $model_3=$Class_::find()->where(["uid"=>$t_id])->one();
  73. if(empty($model_3)){
  74. $model_3 = new $Class_;
  75. $model_3->uid=$t_id;
  76. }
  77. $model_3->position_id1=0;
  78. $model_3->position_id2=0;
  79. $model_3->position_id3=0;
  80. $model_3->position_ids=0;
  81. $model_3->save();
  82. }
  83. }
  84. return $this->renderPartial("tree_list", [
  85. "dataProvider" => $dataProvider,
  86. "searchModel" => $searchModel,
  87. "idField" => $this->idField,
  88. "usernameField" => $this->usernameField,
  89. "extraColumns" => $this->extraColumns,
  90. "data"=>$data_1,
  91. "data_2" => $html,
  92. "model_"=>$model,
  93. "department_ids1" =>!empty($Dep->id)?$Dep->id:"",
  94. "company_id1"=>$UCompany_id,
  95. ]);

注释:1、Yii2 Csrf自动验证功能只有使用$model_2->validate()或者$model_2->save()才能够触发。
2、使用$model->load($post);$post的数组格式如下几种类型,必须的

</>复制代码

  1. Array
  2. (
  3. [User] => Array
  4. (
  5. [parent_id] =>
  6. [t_nickname] => 测试
  7. [t_realname] => 小凌
  8. [t_mobile] =>
  9. [t_email] => 123321@qq.com
  10. )
  11. [department_ids] => Array
  12. (
  13. [0] => 14
  14. [1] => 15
  15. )
  16. [UserProfile] => Array
  17. (
  18. [position]=>Array
  19. (
  20. [0] => 5
  21. [1] => 10
  22. )
  23. )
  24. [_csrf] => LkU4dlE2amdIdVI9AHVZJGYdC058BCctejRbPhdxDQJlBmI3MFkpNQ==
  25. )
常见问题

1、Yii2自带的Csrf验证不起作用。
检查方向:
1.1、是否使用了$model_2->validate()或者$model_2->save(),触发Csrf验证必须有。
1.2、Ajax传过来的数组格式是不是正确的,上面有说明。
1.3、查看控制台报错信息,哪报错从哪找原因。
2、提交表单的时候使用submitButton,使用submitButton的话没法实现无刷新。控制器所需的数据全部都是通过JS获取,Ajax传的方式得到。
3、一大模块全部实现无刷新,有些方法代码量会很大,得把握好它们之间的相关性和其它互不影响性。

相关资料

大侠给讲解一下, $model->load() 与 validate():http://www.yiichina.com/question/955
使用表单:http://www.yiibai.com/yii2/start-forms.html
Ajax+PHP实现动态无刷新技术:http://www.cnblogs.com/freespider/archive/2012/04/11/2442138.html

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/21536.html

相关文章

  • 竞争激烈的互联网时代,是否需要注重一下WEB安全?

    摘要:前言一直以来自己对安全方面的知识了解的比较少,最近有点闲工夫了解了一下。攻击的一般是由服务端解决。攻击条件登录受信任网站,并在本地生成。验证对所有引用对象的授权。 前言 一直以来自己对WEB安全方面的知识了解的比较少,最近有点闲工夫了解了一下。也是为了以后面试吧,之前就遇到过问WEB安全方面的问题,答的不是很理想,所以整理了一下! 一、XSS攻击 跨站脚本攻击(Cross Site ...

    Andrman 评论0 收藏0
  • 竞争激烈的互联网时代,是否需要注重一下WEB安全?

    摘要:前言一直以来自己对安全方面的知识了解的比较少,最近有点闲工夫了解了一下。攻击的一般是由服务端解决。攻击条件登录受信任网站,并在本地生成。验证对所有引用对象的授权。 前言 一直以来自己对WEB安全方面的知识了解的比较少,最近有点闲工夫了解了一下。也是为了以后面试吧,之前就遇到过问WEB安全方面的问题,答的不是很理想,所以整理了一下! 一、XSS攻击 跨站脚本攻击(Cross Site Sc...

    SnaiLiu 评论0 收藏0
  • mpvue开发小程序所遇问题及h5转化方案

    摘要:腾讯地图提供的只提供了经纬度定位,而产品需要的是确认定位后获取城市,进行同城商品检索阿里云对象储存处理文件上传,比较意外的是腾讯对阿里云的域名前缀进行了封禁后台不能配置,解决方案是让后台将该域名进行服务器域名代理。 mpvue开发小程序所遇问题及h5转化方案 项目结构 |---build |---pages.js文件目录 |---src ...

    big_cat 评论0 收藏0
  • 理解CSRF跨站请求伪造

    摘要:受害者在银行有一笔存款,通过对银行的网站发送请求可以使把的存款转到的账号下。大多数情况下,该请求会失败,因为他要求的认证信息。要抵御,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于之中。 受害者 Bob 在银行有一笔存款,通过对银行的网站发送请求 http://bank.example/withdraw?... 可以使 Bob 把 1000000 的存款转到 bob2 的...

    nidaye 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<