http抓包工具 – fiddler、wireshark
http 请求工具 – Postmen(谷歌插件)、RestClient
1、HTTP状态码
200 请求成功
301 重定向,永久移动
302 重定向,临时移动
304 表示读取的缓存数据
401 无权访问
403 拒绝访问
404 找不到页面
405 请求方法不对
500 服务器异常/ 多为代码报错了
更多查看:http://tools.jb51.net/table/http_status_code
2.1、rpc远程调用,httpclient请求方式一(推荐)
pom.xml 依赖,按需添加
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- alibaba - fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.38</version>
</dependency>
<!-- json Obj -->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
<!-- httpclient + httpcore-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
发起请求
青云机器人接口说明:发不同的内容会不同的消息,类似于自动聊天功能
方法一,发起的get请求,参数直接放到了 url 上
方法二,发起的post请求,参数使用body 传递(传递参数为json串,这个不用理会),模拟了请求头 header 传递token 参数
**注意:**返回数据按需处理,我这返回的是json数据,使用转为了json
header 一般存放加密串,然后服务器解析加密串,通过验证才允许访问改接口内容
@SuppressWarnings("ALL")
public class qyRobot implements Serializable {
public static void main(String[] args) {
//get 请求测试
String msg = httpGet("你好呀");
System.out.println(msg);
//post 请求测试
Object obj = httpPost("你好呀");
System.out.println(msg.toString());
}
/**
* httpGet 请求,调用青云机器人接口
*
* @return 回复消息json串示例({"result":0,"content":"哟~ 都好都好"})
* @Param 发送消息:msg
*/
public static String httpGet(String msg) {
String url = "http://api.qingyunke.com/api.php?key=free&appid=0&msg=" + msg;
//参数一,请求参数 new JSONObject() | 参数二,请求头参数 new HttpHeaders(),这里为空
HttpEntity<String> httpEntity = new HttpEntity<String>(null, null);
//发起请求
ResponseEntity<String> responseEntity = new RestTemplate().exchange(url, HttpMethod.GET, httpEntity, String.class);
Map<String, String> mapResponse = JSON.parseObject(responseEntity.getBody(), HashMap.class);
//获得返回的json串
String data = "";
if (MapUtils.isNotEmpty(mapResponse)) {
//获得数据
data = JSON.toJSON(mapResponse).toString();
}
return data;
}
/**
* httpPost 请求
* @param content
* @return
*/
public static Object httpPost(String content) {
String url = "http://api.qingyunke.com/api.php?key=free&appid=0";
//请求参数
JSONObject params = new JSONObject();
params.put("msg",content);
//参数转json串
String json = JSON.toJSONString(params);
//请求头参数
HttpHeaders headers = new HttpHeaders();
headers.add("token","123456");
//放入参数
RestTemplate restTemplate = new RestTemplate();
HttpEntity<String> httpEntity = new HttpEntity<String>(json, headers);
//发起请求获得回调Body参数,mapResponse
ResponseEntity<String> responseEntity =
restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);
Map<String, String> mapResponse = JSON.parseObject(responseEntity.getBody(), HashMap.class);
//参数不为空
Object data = "";
if (MapUtils.isNotEmpty(mapResponse)) {
//返回的参数为Json串
data = JSON.toJSON(mapResponse);
}
return data;
}
}
main 方法测试结果
2.2、rpc远程调用,httpclient请求方式二
此请求方式代码比较乱,要用此方式的自己优化一下了,都和请求方式一大同小异,只不过api 不一样
maven 依赖
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpcore -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
测试代码
- 要传的参数集
params - 特殊字符需要转码
URLEncoder.encode - post 请求
HttpPost url = new HttpPost() - get请求(可把post改为get)
HttpGet url = new HttpGet() - 返回值
responseEntity
@Test
public void doPostTestTwo() {
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
// 参数,字符数据最好encoding以下;这样一来,某些特殊字符才能传过去(如:某人的名字就是“&”,不encoding的话,传不过去)
StringBuffer params = new StringBuffer();
try {
params.append("uid=" + URLEncoder.encode("6548686156", "utf-8"));
params.append("&&serverId="+1);
params.append("&&steps="+112);
params.append("&&msg="+"备注");
params.append("&&emsg="+"英文提示备注");
params.append("&&key=202cb962ac59075b964b07152d234b70");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
HttpPost url = new HttpPost("http://192.168.103.7:88/web/wastageRate/sava"+"?"+params);
url.setHeader("Content-Type", "application/text;charset=utf8");
// 响应模型
CloseableHttpResponse response = null;
try {
// 由客户端执行(发送)Post请求
response = httpClient.execute(url);
HttpEntity responseEntity = response.getEntity();
System.out.println("响应状态为:" + response.getStatusLine());
if (responseEntity != null) {
System.out.println("响应内容长度为:" + responseEntity.getContentLength());
System.out.println("响应内容为:" + EntityUtils.toString(responseEntity));
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (httpClient != null) {
httpClient.close();
}
if (response != null) {
response.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
3、http静态资源防缓存(时间戳)
加载css/js 静态资源一般浏览器都有缓存的
我们修改了 css/js 文件并不会生效,而要清空缓存才会生效
这时我们可以添加时间戳,
这样每次请求浏览器都会默认会是新的地址,重新读取静态资源数据
注意事项:
1、静态文件加载应该定义公共方法,写一个页面单独加载
2、每次重新加载会增大资源开销,应避免改问题
3、公共方法目的为可设置是否添加时间戳/ 是否使用缓存,不需要的时候方便关闭,或不需要使用的静态文件不添加时间戳
----thymeleaf 模板添加时间戳写法
原写法
<link rel="stylesheet" href="../layuiadmin/layui/css/layui.css?time=1" media="all">
现写法
<link rel="stylesheet" th:href="@{../layuiadmin/layui/css/layui.css(time=${new java.util.Date().getTime()})}" media="all">
每次刷新页面时间戳都会改变
其他框架/ 模板什么的,像VUE/ jsp 什么的添加时间戳写法百度找看看
4、http防盗链(防止静态资源被盗用)
防盗链就是盗用其他网站的静态资源,如图片等,自己网站的资源也可能被盗用
解决办法
添加过滤器
获取请求来源, 判断来源
添加过滤器
(1)过滤器(Filter)说明:
它依赖于servlet容器。在实现上,基于函数回调,它可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。使用过滤器的目的,是用来做一些过滤操作,获取我们想要获取的数据,比如:在Javaweb中,对传入的request、response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者Controller进行业务逻辑操作。通常用的场景是:在过滤器中修改字符编码(CharacterEncodingFilter)、在过滤器中修改HttpServletRequest的一些参数(XSSFilter(自定义过滤器)),如:过滤低俗文字、危险字符等。
2、拦截器(Interceptor)说明
拦截器的配置一般在SpringMVC的配置文件中,使用Interceptors标签
拦截器(Interceptor):它依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。在实现上,基于Java的反射机制,属于面向切面编程(AOP)的一种运用,就是在service或者一个方法前,调用一个方法,或者在方法后,调用一个方法,比如动态代理就是拦截器的简单实现,在调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在调用方法后打印出字符串,甚至在抛出异常的时候做业务逻辑的操作。由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理。
public class ImgFilter implements Filter {
public void destroy() {
// TODO Auto-generated method stub
}
/**
*过滤器
*/
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
//获得url 来源
String referer = request.getHeader("referer");
System.out.println("refer is" + "" + referer);
//request.getServerName()
//相当于当前服务器来源,ip 或 请求地址
if (referer == null || !referer.contains(request.getServerName())) {
//不是当前当前服务器获取资源,被非法盗用,重定向到静态资源/ 提示图片告诉对方不要盗用
request.getRequestDispatcher("/static/error.png").forward(request, response);
} else {
//放行
filterChain.doFilter(request, response);
}
}
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
}
5、重定向原理及使用
重定向一般为外部服务器使用
转发一般在内部服务器使用
//转发=页面跳转 --> http://localhost:8080/reqresp_demo/dir1/1.html
request.getRequestDispatcher("/dir1/1.html").forward(request, response);
//重定向,又叫客户端的跳转,显著特征是地址栏发生变化 -->response.sendRedirect("/reqresp_demo5/1.html");
response.sendRedirect("http://www.baidu.com");
/**
* forward(转发) 和 redirect (重定向)的区别
* forward: 是服务器端的跳转,地址栏不发生变化
* redirect: 客户端的跳转,地址栏发生变化
*/
springboot 重定向 || 转发
@RequestMapping("/deleteId")
public String deleteId(Integer id) throws ServletException, IOException {
//重定向本服务器 --> /user/user 接口
//return "redirect:/user/user";
//重定向外服务器
//return "redirect:https://www.baidu.com";
//转发
return "forward:/user/user";
}
响应体说明
Location: http://www.it315.org/index.jsp --表示重定向的地址,该头和302的状态码一起使用。
Server:apache tomcat --表示服务器的类型
Content-Encoding: gzip -- 表示服务器发送给浏览器的数据压缩类型
Content-Length: 80 --表示服务器发送给浏览器的数据长度
Content-Language: zh-cn --表示服务器支持的语言
Content-Type: text/html; charset=GB2312 --表示服务器发送给浏览器的数据类型及内容编码
Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT --表示服务器资源的最后修改时间
Refresh: 1;url=http://www.it315.org --表示定时刷新
Content-Disposition: attachment; filename=aaa.zip --表示告诉浏览器以下载方式打开资源(下载文件时用到)
Transfer-Encoding: chunked
Set-Cookie:SS=Q0=5Lb_nQ; path=/search --表示服务器发送给浏览器的cookie信息(会话管理用到)
Expires: -1 --表示通知浏览器不进行缓存
Cache-Control: no-cache
Pragma: no-cache
Connection: close/Keep-Alive --表示服务器和浏览器的连接状态。close:关闭连接 keep-alive:保存连接
6、https 和http的区别
https 请求过程
https 和 http 比较
1、https 协议需要到 ca 申请证书,一般免费证书较少,因而需要一定费用。
2、http 是超文本传输协议,信息是明文传输,https 则是具有安全性的 ssl 加密传输协议。
3、http 和 https 使用的是完全不同的连接方式,用的端口也不一样,前者是 80,后者是 443。
4、http 的连接很简单,是无状态的;HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 http 协议安全。
https工作原理
我们都知道 HTTPS 能够加密信息,以免敏感信息被第三方获取,所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用 HTTPS 协议。
客户端在使用 HTTPS 方式与 Web 服务器通信时有以下几个步骤,如图所示。
(1)客户使用 https 的 URL 访问 Web 服务器,要求与 Web 服务器建立 SSL 连接。
(2)Web 服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。
(3)客户端的浏览器与 Web 服务器开始协商 SSL 连接的安全等级,也就是信息加密的等级。
(4)客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。
(5)Web 服务器利用自己的私钥解密出会话密钥。
(6)Web 服务器利用会话密钥加密与客户端之间的通信。
https优缺点
虽然说 HTTPS 有很大的优势,但其相对来说,还是存在不足之处的:
(1)HTTPS 协议握手阶段比较费时,会使页面的加载时间延长近 50%,增加 10% 到 20% 的耗电;
(2)HTTPS 连接缓存不如 HTTP 高效,会增加数据开销和功耗,甚至已有的安全措施也会因此而受到影响;
(3)SSL 证书需要钱,功能越强大的证书费用越高,个人网站、小网站没有必要一般不会用。
(4)SSL 证书通常需要绑定 IP,不能在同一 IP 上绑定多个域名,IPv4 资源不可能支撑这个消耗。
(5)HTTPS 协议的加密范围也比较有限,在黑客攻击、拒绝服务攻击、服务器劫持等方面几乎起不到什么作用。最关键的,SSL 证书的信用链体系并不安全,特别是在某些国家可以控制 CA 根证书的情况下,中间人攻击一样可行。