您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

ajax请求controller ajax跨域报错处理

时间:2020-09-03 14:07:15  来源:  作者:

报错:

Access to XMLHttpRequest at 'http://localhost:8080/SpringBootServer/testfile' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

  1. 诱因
    两天研究springboot,因为刚接触没多久springboot,所以遇到了一堆的问题,首先这个springboot我这里建立的是没有web.xml配置文件的,所以在设置过滤器的时候,不知道在哪里设置,导致网上查的一堆在web.xml通过filter设置的过滤器解决跨域问题,我这里都没有用,还有写一写配置文件或者是写一个类文件,配置文件没有,类文件没有用。于是我找了一个晚上,终于找到了解决的办法以及原因,详细如下。
  2. 前台的代码块如下
<!DOCTYPE html>
<html>
 <head>
  <meta charset="UTF-8">
  <title></title>
  <!--我这里使用的是3.4.0的js-->
  <script type="text/JAVAscript" src="js/jquery-3.4.0.js" ></script>
  <script type="text/JavaScript" src="js/jquery-3.4.0.min.js" ></script>
 </head>
 <body>
  <!--一个简单的form表单,测试通过button点击事件,ajax来进行post方式的携带参数发送请求,所以这里没必要写submit和method-->
  <form method="post">
   账号:<input type="text" name="userCode" id="userCode"/><br/>
   密码:<input type="password" name="userPassword" id="userPassword"/><br/>
   <input type="button" value="登录" id="button"/>
  </form>
 </body>
</html>
<script type="text/javascript">
 $button = $("#button")
 /*点击按钮的时候给一个点击事件*/
 $button.click(function(){
  /*得到输入框内的值*/
  var userCode = $("#userCode").val();
  var userPassword = $("#userPassword").val();
  $.ajax({
   type:"post",
   /*你要往哪里发送请求*/
   url:"http://localhost:8080/doLogin",
   data:{
    "userCode":userCode,
    "userPassword":userPassword
   },
   /*设置xhrFields: {withCredentials: true},为true时。
   发送Ajax时,Request header中便会带上 Cookie 信息,否则不携带Cookie
   测试结果如果不写或者不为true的话,后台的session.getid()不是同一个*/
   xhrFields: {withCredentials: true},
   /*crossDomain: true。发送Ajax时,Request header 中会包含跨域的额外信息,
   但不会含cookie。*/
      crossDomain: true,
   dataType:"text",
   success:function(result){
   /*如果成功的话弹一下后台返回的值并且跳转页面到登录成功的页面*/
    alert(result)
    window.location.href="index.html";
   },
   error:function(){
    alert("出错了")
   }
  });
 })
</script>
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. 后台代码块如下,注:这个是springboot项目
package cn.test.controller;
import cn.test.pojo.SmbmsRole;
import cn.test.pojo.SmbmsUser;
import cn.test.service.UserService;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.List;
/**
 * @RestController 声明这个是个controller并且返回的数据类型可以为json
 * @CrossOrigin springboot中支持跨域的注解
 * */
@RestController
@CrossOrigin
public class UserController {
/**
     * @Resource 自动注入的注解
     * */
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private UserService userService;
     /**
     * 进行登录验证的方法
     * 接受ajax传递过来的参数
     * 这里还需要session,response,request来进行一些跨域的设置
     * 亲测,最终成功运行并且结果返回为true
     * */
    @RequestMApping("/doLogin")
    public String doLogin(@RequestParam("userCode")String userCode,
                          @RequestParam("userPassword")String userPassword,
                          HttpSession session, HttpServletResponse response,                          HttpServletRequest request){        /**
         * 测试的输出一下发送请求的域名
         * 最主要的解决问题的代码来了,我这里为了尽量阐述明白查阅了好多资料,写了大量的注释,希望大家可以看的更明白一点
         * */
        System.out.println(request.getHeader("Origin"));
        /**
         *在响应 header 中设置 ‘*’ 来允许来自所有域的跨域请求访问
         * 较灵活的设置方式 允许这个域名进行访问,request.getHeader("Origin"),通过request.getHeader('Origin')来得到访问来源的域名
         * 这行代码很重要,必须写
         * */
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        /**
         * 首部字段 Access-Control-Allow-Headers 表明服务器允许请求中携带字段 X-PINGOTHER 与 Content-Type。
         * Access-Control-Allow-Headers 的值为逗号分割的列表
         * 这个可以不写,写这个就是表明服务器允许请求中携带的字段
         * */
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        /**
         * 前台ajax发送的请求中对应客户端的 xhrFields.withCredentials: true 参数
         * 服务器端通过在响应 header 中设置 Access-Control-Allow-Credentials = true 来运行客户端携带证书式访问。
         * 通过对 Credentials 参数的设置,就可以保持跨域 Ajax 时的 Cookie。这里需要注意的是:
         * 服务器端 Access-Control-Allow-Credentials = true时,参数Access-Control-Allow-Origin 的值不能为 '*'
         * 这是因为请求的首部中携带了 Cookie 信息
         * 如果服务器端的响应中未携带 Access-Control-Allow-Credentials: true ,浏览器将不会把响应内容返回给请求的发送者。
         * 这行代码也必须加
         * */
        response.setHeader("Access-Control-Allow-Credentials", "true");
        System.out.println(session.getId());
        System.out.println("进入了登录验证的方法");
        SmbmsUser smbmsUser = userService.getUser(userCode,userPassword);        session.setAttribute("smbmsUser",smbmsUser);
        if(smbmsUser!=null){
            return "true";
        }else{
            return "false";
        }    } /**
     * 增加数据的控制层方法
     * 这里也需要使用到session,response来进行一系列的设置
     * */
    @RequestMapping(value = "/add",method = RequestMethod.POST)
    public Object addSmbmsRole( SmbmsRole smbmsRole,HttpSession session,HttpServletResponse response,
                                HttpServletRequest request){        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        System.out.println("进入增加数据的方法");
        System.out.println(session.getId());
        System.out.println(((SmbmsUser)session.getAttribute("smbmsUser")).getCreatedBy());
        smbmsRole.setCreatedBy(((SmbmsUser)session.getAttribute("smbmsUser")).getCreatedBy());
        smbmsRole.setCreationDate(new Date());        int count = userService.addSmbmsRole(smbmsRole);        if(count>0){
            return "true";
        }else{
            return"false";
        }    }}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. 测试过程以及一些注意事项
    首先,前端的ajax发送请求时
crossDomain: true,
1

这行代码可以忽略,对结果没有什么较大的影响。
在前台进行设置的时候我还找见一个需要在上面加上以下代码来进行处理,但是对我没有用,你们可以试试

<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
1

测试注掉crossDomain: true,对运行不影响,
测试注掉xhrFields: {withCredentials: true},得到的两个Cookie的ID不一致,出现了问题,所以xhrFields: {withCredentials: true},必备

测试后台只写

response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
1

运行结果进入方法体,但是返回的时候不会进入success方法,进入error方法并且页面报错信息如下

ajax请求controller ajax跨域报错处理

 

 

ajax请求controller ajax跨域报错处理

 

 

ajax请求controller ajax跨域报错处理

 


后台测试只写

response.setHeader("Access-Control-Allow-Credentials", "true");
1

运行结果进入方法体,但是返回的时候不会进入success方法,进入error方法并且页面报错信息如下

ajax请求controller ajax跨域报错处理

 


后台只写

response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
1

会进入后台的方法体,页面都会报错并且弹出error弹窗
测试后台写全

response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
response.setHeader("Access-Control-Allow-Credentials", "true");
123

成功进入方法体,结果成功返回,进入success方法并弹出返回的结果,成功的跳转页面

ajax请求controller ajax跨域报错处理

 

 

ajax请求controller ajax跨域报错处理

 

 

ajax请求controller ajax跨域报错处理

 


测试只写其中的两个,除了只写这两行代码的时候执行成功,其他两种组合方式都以失败告终

response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
12

详细的原因都在代码块的备注中写的很详细了,如果有还不是很懂的可以看下面的链接地址

最终简述一下解决ajax发送跨域的请求的办法
ajax中加入一行代码如下(有的人加上这一句代码后台不用设置就可以,但是我不可以)

xhrFields: {withCredentials: true},
1

Controller的方法体内加入如下两行代码

response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
12

问题成功的解决!

顺便说一下,在你需要对session操作的方法体内和ajax请求,如果ajax加了携带Cookie的代码,后台的方法体内没有加上那两行代码的话,可以对数据进行操作,但是return的时候不会正确的进入到success的方法体内,一直会进入到error的方法。但是值尽然操作成功了,而且还是同一个Cookie,这个问题目前未知,后台加上那两行代码的时候,就一切正常了。
问题,为什么我在登录的时候已经携带了Cookie过去,在其他的ajax请求的时候我也都携带了Cookie,那么为什么我在对Cookie的数据进行操作的时候没有任何问题,但是值确不能正确的返回到前台,无法进入success?
刚才测试的时候又出现的一个新的问题,哎,头疼,脑子已经糊了。

我当时解决问题的参考资料:https://blog.csdn.net/cckevincyh/article/details/81140443
进阶资料:https://blog.csdn.net/wzl002/article/details/51441704
进行配置详细解释的进阶资料:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS#功能概述

强力推荐研究观看两个进阶资料,看了一遍以后虽说不是能瞬间醒悟但是这个资料里面对一些跨域HTTP(CORS)讲解的非常到位,其实搞了半天才解决的原因还是技术太浅了,综上所述其实前台ajax就一行代码就可以解决,后台的Controller只需要两行代码就可以,就这么三行代码,但是我搞了一个晚上才解决,心累啊,找到了解决办法的那一刻,我突然有种想哭的感觉…希望有人看到了之后可以一起研究学习,也希望能给你们提供到帮助!

好了,问题解决了,欣赏一下小姐姐,放松一下吧

ajax请求controller ajax跨域报错处理

 



Tags: ajax跨域   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
报错:Access to XMLHttpRequest at &#39;http://localhost:8080/SpringBootServer/testfile&#39; from origin &#39;null&#39; has been blocked by CORS policy: No &#39;Ac...【详细内容】
2020-09-03  Tags: ajax跨域  点击:(57)  评论:(0)  加入收藏
▌简易百科推荐
摘 要 (OF作品展示)OF之前介绍了用python实现数据可视化、数据分析及一些小项目,但基本都是后端的知识。想要做一个好看的可视化大屏,我们还要学一些前端的知识(vue),网上有很多比...【详细内容】
2021-12-27  项目与数据管理    Tags:Vue   点击:(1)  评论:(0)  加入收藏
程序是如何被执行的&emsp;&emsp;程序是如何被执行的?许多开发者可能也没法回答这个问题,大多数人更注重的是如何编写程序,却不会太注意编写好的程序是如何被运行,这并不是一个好...【详细内容】
2021-12-23  IT学习日记    Tags:程序   点击:(9)  评论:(0)  加入收藏
阅读收获✔️1. 了解单点登录实现原理✔️2. 掌握快速使用xxl-sso接入单点登录功能一、早期的多系统登录解决方案 单系统登录解决方案的核心是cookie,cookie携带会话id在浏览器...【详细内容】
2021-12-23  程序yuan    Tags:单点登录(   点击:(8)  评论:(0)  加入收藏
下载Eclipse RCP IDE如果你电脑上还没有安装Eclipse,那么请到这里下载对应版本的软件进行安装。具体的安装步骤就不在这赘述了。创建第一个标准Eclipse RCP应用(总共分为六步)1...【详细内容】
2021-12-22  阿福ChrisYuan    Tags:RCP应用   点击:(7)  评论:(0)  加入收藏
今天想简单聊一聊 Token 的 Value Capture,就是币的价值问题。首先说明啊,这个话题包含的内容非常之光,Token 的经济学设计也可以包含诸多问题,所以几乎不可能把这个问题说的清...【详细内容】
2021-12-21  唐少华TSH    Tags:Token   点击:(9)  评论:(0)  加入收藏
实现效果:假如有10条数据,分组展示,默认在当前页面展示4个,点击换一批,从第5个开始继续展示,到最后一组,再重新返回到第一组 data() { return { qList: [], //处理后...【详细内容】
2021-12-17  Mason程    Tags:VUE   点击:(14)  评论:(0)  加入收藏
什么是性能调优?(what) 为什么需要性能调优?(why) 什么时候需要性能调优?(when) 什么地方需要性能调优?(where) 什么时候来进行性能调优?(who) 怎么样进行性能调优?(How) 硬件配...【详细内容】
2021-12-16  软件测试小p    Tags:性能调优   点击:(19)  评论:(0)  加入收藏
Tasker 是一款适用于 Android 设备的高级自动化应用,它可以通过脚本让重复性的操作自动运行,提高效率。 不知道从哪里听说的抖音 app 会导致 OLED 屏幕烧屏。于是就现学现卖,自...【详细内容】
2021-12-15  ITBang    Tags:抖音防烧屏   点击:(23)  评论:(0)  加入收藏
11 月 23 日,Rust Moderation Team(审核团队)在 GitHub 上发布了辞职公告,即刻生效。根据公告,审核团队集体辞职是为了抗议 Rust 核心团队(Core team)在执行社区行为准则和标准上...【详细内容】
2021-12-15  InfoQ    Tags:Rust   点击:(24)  评论:(0)  加入收藏
一个项目的大部分API,测试用例在参数和参数值等信息会有很多相似的地方。我们可以复制API,复制用例来快速生成,然后做细微调整既可以满足我们的测试需求1.复制API:在菜单发布单...【详细内容】
2021-12-14  AutoMeter    Tags:AutoMeter   点击:(20)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条