1.关于跨域的说明
1.1 跨域访问测试
测试1: 同服务器测试
说明:
1.浏览器的网址信息: http://manage.jt.com/test.html
2.ajax请求的地址信息: http://manage.jt.com/test.json
发现: 请求协议名称://域名:端口号都相同时,请求可以正常进行.
测试2: 不同的服务器测试
说明:;
1.浏览器的网址信息: http://www.jt.com/test.html
2.ajax请求的地址信息: http://manage.jt.com/test.json
结论: 域名地址不相同时请求不能正常获取响应的结果.
1.2 同源策略介绍
说明:
浏览器在解析ajax时,如果发现请求的协议名称://请求的域名:请求的端口号与网址的地址都相同的时满足同源策略的规定,浏览器可以正确的解析返回值.该访问称之为同域访问.该策略叫做同源策略.
但是如果违反了同源策略中的任意一条,则叫做跨域访问.浏览器出于安全性的考虑.不予解析返回值(请求正常的被处理,但是接收不到返回值).
概括: 浏览器解析ajax时,由于请求违反了同源策略则称之为跨域请求.
例子: http://localhost:8091/xxx.html
http://manage.jt.com/xx.html 不可以通讯
1.3 JSONP实现跨域
1.3.1 JSONP实现跨域的原理(有难度)
1.javaScript中的src属性不受同源策略的约束.可以获取远程服务器数据.
<!--该json一直保存到浏览器中等待调用,但是没有函数名称无法调用 -->
<script type="text/javascript" src="http://manage.jt.com/test.json"></script>
2.自定义回调函数 名称任意
/*定义回调函数 */
function hello(data){
alert(data.name);
}
3.将返回值结果进行特殊的格式封装 callback(JSON);
hello({
"id":"1","name":"tomcat猫"})
1.3.2 JSONP优化策略
1.利用script中的src属性发起请求不方便.不便于程序使用. 能否封装为ajax调用方式
2.在请求路径中拼接一个参数一般的key都是约定俗称的 http:xxx/xx?callback=“自定义函数名称”
3.动态的获取callback的参数名称之后进行特殊的格式封装 callback(JSON);
1.3.3 JSONP概念
JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的
1.3.3 JSONP的Ajax调用
<script type="text/javascript">
$(function(){
alert("测试访问开始!!!!!")
$.ajax({
url:"http://manage.jt.com/web/testJSONP",
type:"get", //jsonp只能支持get请求 src只能是get请求
dataType:"jsonp", //dataType表示返回值类型
//jsonp: "callback", //指定参数名称
//jsonpCallback: "hello", //指定回调函数名称
success:function (data){
//data经过jQuery封装返回就是json串
alert(data.itemId);
alert(data.itemDesc);
}
});
})
</script>
1.3.4 编辑后台Controller返回数据
package com.jt.web.controller;
import com.jt.pojo.ItemDesc;
import com.jt.util.ObjectMapperUtil;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class JSONPController {
/**
* 测试跨域访问是否成功
* url地址: http://manage.jt.com/web/testJSONP?callback=jQuery111106536880527642785_1600138715329&_=1600138715330
* 返回值的应该是经过特殊格式封装的数据. callback(JSON)
*/
@RequestMapping("/web/testJSONP")
public String jsonp(String callback){
ItemDesc itemDesc = new ItemDesc();
itemDesc.setItemId(100L).setItemDesc("跨域测试成功!!!!");
String json = ObjectMapperUtil.toJSON(itemDesc);
return callback+"("+json+")";
}
}
1.3.5 编辑JSONPObject对象
/**
* 测试跨域访问是否成功
* url地址: http://manage.jt.com/web/testJSONP?callback=jQuery111106536880527642785_1600138715329&_=1600138715330
* 返回值的应该是经过特殊格式封装的数据. callback(JSON)
* JSONPObject参数说明:
* 1.function 回调函数名称
* 2.返回的对象之后可以被转化为JSON
*/
@RequestMapping("/web/testJSONP")
public JSONPObject jsonp(String callback){
ItemDesc itemDesc = new ItemDesc();
itemDesc.setItemId(100L).setItemDesc("API测试!!!");
return new JSONPObject(callback, itemDesc);
}
1.3.6 关于ajax请求时间毫秒数的说明
说明:由于浏览器内部有缓存机制,所以如果遇到了一个相同的请求地址,浏览器可能会使用之间的结果.(使用缓存),但是有些数据必须要求浏览器重数据库中动态获取数据,为了避免浏览器缓存一般在url最后添加随机数或者时间毫秒数区分url请求.实现该功能.
1.4 CORS跨域方式
1.4.1 跨域访问测试
<script type="text/javascript">
/*$(){}结构必然是jQuery函数类库导入后才能正确执行*/
$(function(){
alert("我执行了AJAX");
//利用jQuery发起AJAX请求
$.get("http://manage.jt.com/test.json",function(data){
alert(data.name);
})
})
</script>
1.4.2 CORS跨域说明
说明:当下的主流的浏览器默认支持cors跨域的形式,但是需要服务器添加响应的信息.否则浏览器不支持数据的获取.
1.4.3 编辑CORS配置类
说明:在jt-common中添加CORS的配置类
package com.jt.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CORSConfig implements WebMvcConfigurer {
/**
* 实现跨域的方式
* 需要配置服务端程序
* 方法说明:
* 1.addMapping(/**) 允许什么样的请求可以跨域 所有的请求
* 2.allowedOrigins("*")可以允许任意的域名
* 3.allowCredentials(true) 跨域时是否允许携带cookie等参数
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true);
}
}
1.4.4 跨域测试
2. 京淘单点登录系统
2.1 通用页面跳转
2.1.1 业务分析
1.注册的url地址
http://www.jt.com/user/register.html
2.登录的url地址
http://www.jt.com/user/login.html
2.1.2 编辑UserController
package com.jt.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller //由于设计到页面跳转功能.
@RequestMapping("/user")
public class UserController {
/**
* 通用页面跳转实现
* 1.http://www.jt.com/user/login.html login.jsp页面
* 2.http://www.jt.com/user/register.html register.jsp页面
*/
@RequestMapping("/{moduleName}")
public String module(@PathVariable String moduleName){
return moduleName;
}
}
2.1.3 页面效果展现
2.2 创建JT-SSO项目
2.2.1 JT-SSO项目说明
作用:主要为jt-web的服务器提供用户的数据的支持,但凡涉及到user的CRUD操作都应该由该系统完成.
打包方式: jar包程序
注意事项: 继承jt/ 依赖jt-common 添加插件.
端口号: 8093
2.2.2 创建项目
2.2.3 编辑pom.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>jt-sso</artifactId>
<parent>
<artifactId>jt</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<!--添加依赖项-->
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>jt-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<!--添加插件-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.2.4 编辑User的POJO对象
@TableName("tb_user")
@Data
@Accessors(chain = true)
public class User extends BasePojo{
@TableId(type = IdType.AUTO) //主键自增
private Long id;
private String username; //用户名
private String password; //密码
private String phone; //电话
private String email; //邮箱 由于email暂时没有使用电话代替
}
2.2.4 实现JT-SSO代码结构
2.2.5 编辑Nginx实现反向代理
注意hosts文件的配置. 修改nginx之后重启服务器.
#搭建jt-sso服务器
server {
listen 80;
server_name sso.jt.com;
location / {
proxy_pass http://localhost:8093;
}
}
2.3 用户数据校验的分析
2.3.1 页面url分析
2.3.2 检索页面JS
2.3.3 页面JS分析
$.ajax({
url : "http://sso.jt.com/user/check/"+escape(pin)+"/1?r=" + Math.random(),
dataType : "jsonp",
success : function(data) {
//状态信息:200 成功 状态信息:201 失败
checkpin = data.data?"1":"0";
if(data.status == 200){
if (!data.data) {
validateSettings.succeed.run(option);
namestate = true;
}else {
validateSettings.error.run(option, "该用户名已占用!");
namestate = false;
}
}else{
//标识后台服务器运行异常
validateSettings.error.run(option, "服务器正忙,请稍后!!!(我后台报错了我也不知道啥错!!!)");
namestate = false;
}
}
});
2.2.6 单点登录业务接口
2.2.7 编辑jt-sso的UserController
package com.jt.controller;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.jt.pojo.User;
import com.jt.service.UserService;
import com.jt.vo.SysResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/findAll")
public List<User> findAll(){
return userService.findAll();
}
/**
* JSONP的跨域请求 特殊的格式封装.....
* 需求分析:校验用户的数据是否可用.
* url: http://sso.jt.com/user/check/{param}/{type}
* 参数: param/type
* 返回值结果: SysResult对象
*/
@RequestMapping("/check/{param}/{type}")
public JSONPObject chcekUser(@PathVariable String param,
@PathVariable Integer type,
String callback){
//根据信息查询数据库获取响应记录
Boolean flag = userService.checkUser(param,type);
return new JSONPObject(callback, SysResult.success(flag));
}
}
2.2.8 编辑jt-sso的UserService
package com.jt.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class UserServiceImpl implements UserService{
private static Map<Integer,String> paramMap = new HashMap<>();
static {
paramMap.put(1, "username");
paramMap.put(2, "phone");
paramMap.put(3, "email");
}
@Autowired
private UserMapper userMapper;
@Override
public List<User> findAll() {
return userMapper.selectList(null);
}
/**
* 校验数据是否存在即可. 查询总记录数即可.
* @param param 需要校验的数据
* @param type 校验的类型 1username 2phone 3 email 6789910
* @return
*/
@Override
public Boolean checkUser(String param, Integer type) {
String column = paramMap.get(type);
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(column, param);
//boolean flag = userMapper.selectCount(queryWrapper)>0?true:false;
return userMapper.selectCount(queryWrapper)>0;
}
}
2.2.9 页面效果展现
2.2.10 修改全局异常处理机制
package com.jt.aop;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.jt.vo.SysResult;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
@RestControllerAdvice //作用: 标识我是一个通知方法,并且只拦截Controll层的异常.并且返回JSON.
public class SysResultException {
//需要定义一个全局的方法 返回指定的报错信息.
//ExceptionHandler 配置异常的类型,当遇到了某种异常时在执行该方法.
//JSONP的异常处理应该是 callback({status:201,msg:"",data:""})
//利用Request对象动态获取callback参数.之后动态封装返回值
@ExceptionHandler(RuntimeException.class)
public Object exception(Exception e, HttpServletRequest request){
e.printStackTrace();
String callback = request.getParameter("callback");
if(!StringUtils.isEmpty(callback)){
//jsonp请求
return new JSONPObject(callback, SysResult.fail());
}
//日志记录/控制台输出. 让程序员知道哪里报错!!!
return SysResult.fail();
}
}
3.微服务框架介绍
3.1远程调用的说明
浏览器解析ajax发起跨域请求.程序虽然可以正确的调用,但是浏览器可以监控用户的所有的参数及返回值.在一些特定的条件下该操作不安全.
一般使用跨域的请求都是用来获取其他服务器的数据(查询操作),如果遇到了POST需要提交的参数应该使用更加安全的请求方式实现.
3.2 HttpClient介绍
HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。虽然在 JDK 的 java net包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。HttpClient 已经应用在很多的项目中,比如 Apache Jakarta 上很著名的另外两个开源项目 Cactus 和 HTMLUnit 都使用了 HttpClient。现在HttpClient最新版本为 HttpClient 4.5 .6(2015-09-11)
3.3 HttpClient入门案例
3.3.1 导入jar包
<!--添加httpClient jar包 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
3.3.2 入门案例
package com.jt.test;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.junit.jupiter.api.Test;
import java.io.IOException;
public class TestHttpClient {
/**
* 步骤:
* 1.实例化httpClient工具API
* 2.定义请求url地址 任意网络地址....
* 3.定义请求的类型 get/post/put/delete
* 4.发起请求,获取响应的结果
* 5.判断响应的状态码信息. 200 404 500 406 400....
* 6.动态解析返回值执行后续操作.
*/
@Test
public void test01(){
HttpClient httpClient = HttpClients.createDefault();
String url = "https://www.baidu.com/";
HttpGet get = new HttpGet(url);
try {
HttpResponse httpResponse = httpClient.execute(get);
//判断状态码是否正确
int statusCode = httpResponse.getStatusLine().getStatusCode();
if(statusCode == 200){
//表示请求正确
HttpEntity httpEntity = httpResponse.getEntity(); //获取服务器的全部响应信息(json/html/xml/xxxx)
String result = EntityUtils.toString(httpEntity,"UTF-8");
//获取之后可以执行业务处理......
System.out.println(result);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
来源:oschina
链接:https://my.oschina.net/u/4349274/blog/4589086