热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

慕课网_《Ajax跨域完全讲解》学习总结

时间:2018年04月18日星期三说明:本文部分内容均来自慕课网。@慕课网:https:www.imooc.com教学源码:https:github.comzccoderes…学习

时间:2018年04月18日星期三
说明:本文部分内容均来自慕课网。@慕课网:https://www.imooc.com
教学源码:https://github.com/zccodere/s…
学习源码:https://github.com/zccodere/s…

第一章:课程介绍

1-1 课程介绍

课程介绍

  • 什么是AJAX跨域问题
  • 产生AJAX跨域问题的原因
  • 解决AJAX跨域问题的思路和方法

什么是AJAX跨域问题

  • 简单来说,就是前端调用后端服务接口时
  • 如果服务接口不是同一个域,就会产生跨域问题

AJAX跨域场景

  • 前后端分离、服务化的开发模式
  • 前后端开发独立,前端需要大量调用后端接口的场景
  • 只要后端接口不是同一个域,就会产生跨域问题
  • 跨域问题很普遍,解决跨域问题也很重要

AJAX跨域原因

  • 浏览器限制:浏览器安全校验限制
  • 跨域(协议、域名、端口任何一个不一样都会认为是跨域)
  • XHR(XMLHttpRequest)请求

AJAX跨域问题解决思路

  • 浏览器:浏览器取下跨域校验,实际价值不大
  • XHR:不使用XHR,使用JSONP,有很多弊端,无法满足现在的开发要求
  • 跨域:被调用方修改支持跨域调用(指定参数);调用方修改隐藏跨域(基于代理)

编写测试代码

  • 被调用方后端代码编写:Spring Boot
  • 调用方前端代码编写:Jquery
  • 引入前端Jasmine测试框架
第二章:环境搭建

2-1 后端项目

代码编写

1.创建名为ajax-server的maven工程pom如下


xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
com.myimooc
ajax-server
0.0.1-SNAPSHOT
jar
ajax-server
Demo project for Spring Boot

org.springframework.boot
spring-boot-starter-parent
2.0.1.RELEASE



UTF-8
UTF-8
1.8



org.springframework.boot
spring-boot-starter-web


org.springframework.boot
spring-boot-starter-test
test





org.springframework.boot
spring-boot-maven-plugin




2.编写AjaxServerStart类

package com.myimooc.ajax.server;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
*

* 标题: 启动类

* 描述: AJAX跨域讲解后端项目

*
* @author zc
* @date 2018/04/18
*/
@SpringBootApplication
public class AjaxServerStart {
public static void main(String[] args) {
SpringApplication.run(AjaxServerStart.class, args);
}
}

3.编写ResultBean类

package com.myimooc.ajax.server.vo;
import java.io.Serializable;
/**
*

* 标题: REST请求响应POJO类

* 描述: 封装请求响应结果

*
* @author zc
* @date 2018/04/18
*/
public class ResultBean implements Serializable{
private static final long serialVersiOnUID= 7867107433319736719L;
private String data;
public ResultBean(String data) {
this.data = data;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}

4.编写TestController类

package com.myimooc.ajax.server.controller;
import com.myimooc.ajax.server.vo.ResultBean;
import com.myimooc.ajax.server.vo.User;
import org.springframework.web.bind.annotation.*;
/**
*

* 标题: 测试控制器

* 描述: 提供REST服务

* 使用 @CrossOrigin 注解支持跨域,可以放到类或方法上面
* @author zc
* @date 2018/04/18
*/
@RestController
@RequestMapping("/test")
//@CrossOrigin
public class TestController {
@GetMapping("/get1")
public ResultBean get1() {
System.out.println("TestController.get1");
return new ResultBean("get1ok");
}
@PostMapping("/postJson")
public ResultBean postJson(@RequestBody User user) {
System.out.println("TestController.postJson");
return new ResultBean("postJson" + user.getName());
}
@GetMapping("/getCOOKIE")
public ResultBean getCOOKIE(@COOKIEValue(value = "COOKIE1") String COOKIE1) {
System.out.println("TestController.getCOOKIE");
return new ResultBean("getCOOKIE" + COOKIE1);
}
@GetMapping("/getHeader")
public ResultBean getHeader(
@RequestHeader("x-header1") String header1,
@RequestHeader("x-header2") String header2) {
System.out.println("TestController.getHeader");
return new ResultBean("getHeader" + header1+header2);
}
}

2-2 前端项目

代码编写

1.创建名为ajax-client的maven工程pom如下


xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
com.myimooc
ajax-client
0.0.1-SNAPSHOT
jar
ajax-client
Demo project for Spring Boot

org.springframework.boot
spring-boot-starter-parent
2.0.1.RELEASE



UTF-8
UTF-8
1.8



org.springframework.boot
spring-boot-starter-web


org.webjars
jquery
3.3.0


org.webjars
jasmine
2.5.0





org.springframework.boot
spring-boot-maven-plugin




2.编写index.html













发生get1请求


3.编写application.properties

server.port=8081

4.编写AjaxClientStart类

package com.myimooc.ajax.client;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class AjaxClientStart {
public static void main(String[] args) {
SpringApplication.run(AjaxClientStart.class, args);
}
}

5.启动AjaxServerStart和AjaxClientStart,并访问http://localhost:8081,点击发生get1请求,产生跨域问题如下

《慕课网_《Ajax跨域完全讲解》学习总结》

第三章:解决跨域

3-1 禁止检查

Chrome浏览器的跨域设置

  • Windows方法
  • 参考文档:https://www.cnblogs.com/laden…
  • 使用说明:在属性页面中的目标输入框里加上:–disable-web-security –user-data-dir=C:MyChromeDevUserData
  • Mac OS方法
  • 参考文档:http://blog.csdn.net/justinji…
  • 使用说明:用命令行打开 Google Chrome:open -a “Google Chrome” –args –disable-web-security

3-2 使用JSONP

代码编写

1.编写JsonpAdvice类

package com.myimooc.ajax.server.controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.AbstractJsonpResponseBodyAdvice;
/**
*

* 标题: JSONP 全局处理

* 描述: 统一处理JSONP

*
* @author zc
* @date 2018/04/18
*/
@ControllerAdvice
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice{
public JsonpAdvice() {
// 与前端约定好回调方法名称,默认是callback
super("callback2");
}
}

2.修改index.html

// 测试方法
it("jsonp请求", function (done) {
// 服务器返回的结果
var result;
$.ajax({
url: base + "/get1",
dataType: "jsonp",
jsonp:"callback2",
success: function (res) {
result = res;
}
});
// 由于是异步请求,需要使用setTimeout来校验
setTimeout(function () {
expect(result).toEqual({
"data":"get1ok"
});
// 校验完成,通知jasmine框架
done();
},100);
});

JSONP的弊端

  • 服务器需要改动代码支持
  • 只支持GET
  • 发送的不是XHR请求

3-3 支持跨域

常见的JavaEE架构

《慕课网_《Ajax跨域完全讲解》学习总结》

跨域解决方向

  • 被调用方解决
  • 基于支持跨域的解决思路
  • 基于Http协议关于跨域的相关规定,在响应头里增加指定的字段告诉浏览器,允许调用
  • 跨域请求是直接从浏览器发送到被调用方
  • 修改被调用方的Http服务器
  • 调用方解决
  • 基于隐藏跨域的解决思路
  • 跨域请求不会浏览器直接发送到被调用方
  • 而是从中间的Http服务器(Apache、Nginx)转发过去
  • 修改调用方的Http服务器

被调用方支持跨域

  • 【重点】Web应用服务器(Tomcat、Netty、WebLogic或应用程序)实现
  • Http服务器(Nginx)配置实现
  • Http服务器(Apache)配置实现

使用Filter解决

编写代码

1.编写CrosFilter类

package com.myimooc.ajax.server.config;
import org.springframework.util.StringUtils;
import javax.servlet.*;
import javax.servlet.FilterConfig;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
*

* 标题: 服务端解决跨域

* 描述: 使用Filter

*
* @author zc
* @date 2018/04/18
*/
public class CrosFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse)response;
HttpServletRequest req = (HttpServletRequest)request;
// 支持所有域
String origin = req.getHeader("Origin");
if (!StringUtils.isEmpty(origin)){
// 支持任何域名的跨域调用 且 支持带COOKIE(是被调用方域名的COOKIE,而不是调用方的COOKIE)
res.addHeader("Access-Control-Allow-Origin",origin);
}
// 指定允许的域,带COOKIE时,origin必须是全匹配,不能使用 *
// res.addHeader("Access-Control-Allow-Origin","http://localhost:8081");
// 允许所有域,但不能满足带 COOKIE 的跨域请求
// res.addHeader("Access-Control-Allow-Origin","*");
// 支持所有自定义头
String headers = req.getHeader("Access-Control-Allow-Headers");
if (!StringUtils.isEmpty(headers)){
// 允许所有header
res.addHeader("Access-Control-Allow-Headers",headers);
}
// 允许所有header
// res.addHeader("Access-Control-Allow-Headers","*");
// 指定允许的方法
// res.addHeader("Access-Control-Allow-Methods","GET");
// 允许所有方法
res.addHeader("Access-Control-Allow-Methods","*");
// 允许浏览器在一个小时内,缓存跨域访问信息(即上面三个信息)
res.addHeader("Access-Control-Max-Age","3600");
// 启用 COOKIE
res.addHeader("Access-Control-Allow-Credentials","true");
chain.doFilter(request,response);
}
@Override
public void destroy() {
}
}

2.编写FilterConfig类

package com.myimooc.ajax.server.config;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
*

* 标题: 配置类

* 描述: 注册CrosFilter

*
* @author zc
* @date 2018/04/18
*/
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean registrationBean(){
FilterRegistrationBean filter = new FilterRegistrationBean();
filter.addUrlPatterns("/*");
filter.setFilter(new CrosFilter());
return filter;
}
}

3.启动AjaxServerStart和AjaxClientStart,并访问http://localhost:8081,跨域解决

《慕课网_《Ajax跨域完全讲解》学习总结》

简单请求与非简单请求

  • 简单请求:浏览器先发送真正的请求后检查
  • 请求方法:GET、HEAD、POST的一种
  • 请求header:无自定义header;Content-Type为:text/plain、multipart/form-data、application/x-www-form-urlencoded的一种
  • 非简单请求:浏览器先发预检命令,检查通过后,才发送真正的请求
  • 常见的有:PUT、DELETE
  • 其它条件:发送Json格式的请求、带自定义header的请求
  • 预检命令:浏览器检测到跨域请求, 会自动发出一个OPTIONS请求, 就是所谓的预检(preflight)请求。当预检请求通过的时候,才发送真正的请求。

Nginx配置

  • 修改主机hosts文件增加映射本地域名:127.0.0.1 b.com(表示被调用方的域名)
  • 在conf目录下创建vhost目录
  • 修改nginx.conf在最后面增加一行代码:include vhost/*.conf;
  • 在vhost目录下创建b.com.conf
  • 启动niginx,访问b.com/test/get1

编写b.com.conf

server{
listen 80;
server_name b.com;
location /{
proxy_pass http://localhost:8080/;
add_header Access-Control-Allow-Methods *;
add_header Access-Control-Max-Age 3600;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Headers $http_access_control_allow_headers;
if ($request_method = OPTIONS){
return 200;
}
}
}

Apache配置

  • 修改conf/httpd.conf找到LoadModule vhost_alias_module module/mod_vhost_alias.so取消注释
  • 修改conf/httpd.conf找到LoadModule proxy_module module/mod_ proxy.so取消注释
  • 修改conf/httpd.conf找到LoadModule proxy_http_module module/mod_ proxy_http.so取消注释
  • 修改conf/httpd.conf找到LoadModule headers_module module/mod_ headers.so取消注释
  • 修改conf/httpd.conf找到LoadModule rewrite_module module/mod_ rewrite.so取消注释
  • 修改conf/httpd.conf找到Include conf/extra/httpd-vhosts.conf取消注释
  • 修改conf/extra/httpd-vhosts.conf在最后面增加下面的内容即可


ServerName b.com
ErrorLog "logs/b.com-error.log"
CustomLog "logs/b.com-access.log" common
ProxyPass / http://localhost:8080/
# 把请求头的origin值返回到Access-Control-Allow-Origin字段
Header always set Access-Control-Allow-Origin "expr=%{req:origin}"
# 把请求头的Access-Control-Allow-Headers值返回到Access-Control-Allow-Headers字段
Header always Access-Control-Allow-Headers "expr=%{Access-Control-Allow-Headers}"
Header always set Access-Control-Allow-Methods "*";
Header always set Access-Control-Max-Age "3600";
Header always set Access-Control-Allow-Credentials ""true";
# 处理预检命令OPTIONS,直接返回204
RewriteEngine On
RewriteCond %{REQUEST_METHOD}OPTIONS
RewriteRule ^(.*)$"/" [R=204,L]

Spring框架支持

  • 在类或方法上使用注解@CrossOrigin即可支持跨域

3-4 隐藏跨域

使用Nginx反向代理实现

  • 修改主机hosts文件增加映射本地域名:127.0.0.1 a.com
  • 在vhost目录下创建a.com.conf
  • 启动niginx,访问a.com/ajaxserver/get1

编写a.com.conf

server{
listen 80;
server_name a.com;
location /{
proxy_pass http://localhost:8081/;
}
location /ajaxserver{
proxy_pass http://localhost:8080/test/;
}
}

使用Apache反向代理实现

  • 修改conf/extra/httpd-vhosts.conf在最后面增加下面的内容即可


ServerName a.com
ErrorLog "logs/a.com-error.log"
CustomLog "logs/a.com-access.log" common
ProxyPass / http://localhost:8081/
ProxyPass /ajaxserverapache http://localhost:8080/test

第四章:课程总结

4-1 课程总结

课程总结

  • 产生原因:主要是浏览器对Ajax请求的限制
  • 解决思路:JSONP、支持跨域、隐藏跨域
  • 核心原理:了解Http协议关于跨域方面的规定
  • 解决方法:使用Filter、Nginx正反向代理、Apache正反向代理、Spring框架支持

推荐阅读
  • 在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板
    本文介绍了在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板的方法和步骤,包括将ResourceDictionary添加到页面中以及在ResourceDictionary中实现模板的构建。通过本文的阅读,读者可以了解到在Xamarin XAML语言中构建控件模板的具体操作步骤和语法形式。 ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • iOS超签签名服务器搭建及其优劣势
    本文介绍了搭建iOS超签签名服务器的原因和优势,包括不掉签、用户可以直接安装不需要信任、体验好等。同时也提到了超签的劣势,即一个证书只能安装100个,成本较高。文章还详细介绍了超签的实现原理,包括用户请求服务器安装mobileconfig文件、服务器调用苹果接口添加udid等步骤。最后,还提到了生成mobileconfig文件和导出AppleWorldwideDeveloperRelationsCertificationAuthority证书的方法。 ... [详细]
  • 本文讨论了如何使用Web.Config进行自定义配置节的配置转换。作者提到,他将msbuild设置为详细模式,但转换却忽略了带有替换转换的自定义部分的存在。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • t-io 2.0.0发布-法网天眼第一版的回顾和更新说明
    本文回顾了t-io 1.x版本的工程结构和性能数据,并介绍了t-io在码云上的成绩和用户反馈。同时,还提到了@openSeLi同学发布的t-io 30W长连接并发压力测试报告。最后,详细介绍了t-io 2.0.0版本的更新内容,包括更简洁的使用方式和内置的httpsession功能。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • r2dbc配置多数据源
    R2dbc配置多数据源问题根据官网配置r2dbc连接mysql多数据源所遇到的问题pom配置可以参考官网,不过我这样配置会报错我并没有这样配置将以下内容添加到pom.xml文件d ... [详细]
author-avatar
以下犯上LOVE_845
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有