-
Nginx跨域问题,分别向两台服务器上传下面的两个页面,其中第一个页面调用第二个页面中的内容:
a.jsp中的内容:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>177节点</title> </head> <script src="https://code.jquery.com/jquery-2.2.4.js" integrity="sha256-iT6Q9iMJYuQiMWNd9lDyBUStIq/8PuOW33aOqmvFpqI=" crossorigin="anonymous"></script> <script type="text/javascript"> $(document).ready(function() { $.ajax({ type: "get", url: "http://www.kangswx/b.jsp", dataType: "text", success: function(data) { debugger; alert("获取178结果:" + data); }, error: function(e) { debugger; alert('失败:' + e); } }); }); </script> <body> 我是177节点 </body> </html>
b.jsp中的内容:
<% response.setContentType("application/json;charset=utf-8"); out.print("{'status':'200', 'message':'178节点NGINX1'}"); %>
此时若直接访问 http://192.168.18.177:8080/a.jsp,回报如下的错误(跨域问题):No ‘Access-Control-Allow-Origin’ header is present on the requested resource。
需要在Nginx的配置文件中做如下的修改:
upstream serveraaalist{ server 192.168.18.177:8080; } upstream serverbbblist{ server 192.168.18.178:8080; } location /a { proxy_pass http://serveraaalist/a; } location /b { proxy_pass http://serverbbblist/b; }
在a.jsp中掉用b.jsp的时候,需要通过域名调用 http://www.kangswx/b.jsp
此时访问 http://www.kangswx.com/a.jsp 就能正常获取b中的数据。
-
盗链:
客户端向服务端发起请求的时候,为了减少网络宽带,提高响应速度,服务器一般不会把所有的资源都完整的返回给客户端,比如在请求一个网页时,首先会传回该网页的文本内容,当客户端浏览器发现有图片需要加载的时候,会再次向服务器发起请求获取图片资源,服务器再将图片资源返回给客户端,在这个过程中,如果该服务器只包含网页文本内容,并没有相关的要从本地服务器加载图片资源,而是去其他网站加载图片资源,只就是盗链。
-
防止盗链:
HTTP协议中的请求头部的Referer头域和采用URL的格式表示访问当前网页或者文件的源地址。通过Referer头,就可以检测到访问目标资源的源地址。当发现Referer头不是我们自己网站的内的URL,就采用阻止措施,实施防盗链。但是,Referer是可以被篡改的,因此应该方法不能够完全防止盗链。
-
Nginx防盗链:Nginx配置有个valid_referers指令,用来获取Referer头中值,根据该值的情况给Nginx全局变量invalid_referer赋值,如果Referer头中没有符合的valid_referes指令配置的值,invalid_referer全局变量就会被赋值为1。
-
valid_referers指令语法格式:
格式:valid_referers none | blocked | server_names | string……;
none: 检测Referer头域不存在的情况;
blocked: 检测Referer头域值被防火墙或代理服务器删除或伪装的情况;
server_name:设置一个或多个URL, 用于Referer头域值是否属于URL中的某个值, URL支持通配符;
-
Nginx防盗链配置方式,在原有location下面,新加一个新的location,如下
location ~ .*\.(jpg|jpeg|png|gif|icon|rar|zip|swf)$ { valid_referers blocked http://www.kangswx.com www.kangswx.com; if ($invalid_referer) { return 403; # 资源不可用 } }
-
Nginx防御DDOS攻击:限制请求次数,设置Nginx的连接请求在一个真实用户请求的合理范围内。
-
Nginx防御DDOS攻击的配置方式
-
在配置文件server的上面添加如下的内容
limit_req_zone $binary_remote_addr zone=one:10m rate=2r/s;
-
在location中加入
limit_req zone=one;
-
-
参数说明
$binary_remote_addr 二进制远程地址 zone=one:10m 定义zone名字叫one,并为这个zone分配10M内存,用来存储会话(二进制远程地址),1m内存可以保存16000会话 rate=10r/s; 限制频率为每秒10个请求 burst=5 允许超过频率限制的请求数不多于5个,假设1、2、3、4秒请求为每秒9个,那么第5秒内请求15个是允许的,反之,如果第一秒内请求15个,会将5个请求放到第二秒,第二秒内超过10的请求直接503,类似多秒内平均速率限制。 nodelay 超过的请求不被延迟处理,设置后15个请求在1秒内处理。 -
此时当请求数量超限的时候,页面会报如下的错误
-
Nginx解决session共享有四种方案:
- 使用Nginx的负载均衡中的ip_hash配置(不推荐);
- 使用数据库同步session(不推荐);
- 使用cookie同步session(不推荐);
- 使用redis存放session数据
-
运行SpringBoot的jar文件:
nohup java -jar springboot-session-8081.jar &
-
模拟session不共享示例代码,新建一个SpringBoot项目,新建一个测试controller,代码如下:
package com.kangswx.springbootsession.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; @RestController public class SessionController { //开放的端口号 @Value("${server.port}") private String port; @GetMapping("/setSession") public String setSession(HttpServletRequest request, String key, String value) { HttpSession session = request.getSession(); session.setAttribute(key, value); String rs = "setSession Server Port:" + port + " Value:" + value; System.out.println(rs); return rs; } @GetMapping("/getSession") public String getSession(HttpServletRequest request, String key) { HttpSession session = null; String value = null; try { session = request.getSession(false); if (session != null) value = (String)session.getAttribute(key); } catch (Exception e) { e.printStackTrace(); } String rs = "getSession Server Port:" + port + " Value:" + value; System.out.println(rs); return rs; } }
-
分别上传到 192.168.18.177 和 192.168.18.178 两台服务器,并且在Nginx中将上述两台服务器配置好,启动SpringBoot项目(192.168.18.177开放的端口的8081,192.168.18.178开放的端口为8082):
首先向某个服务器中写入session:
再多次获取session的时候,就会出现session不共享的问题:
-
SpringBoot解决session共享问题:
-
在之前的项目中添加相关依赖的maven坐标:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> </dependency>
-
在SpringBoot项目的配置文件中加入下面的配置项:
spring: redis: host: 192.168.18.177 port: 6379 password: redis database: 2 #将session存储在Redis中,实现session共享的问题 session: store-type: redis
-
将项目分别打成对应的jar包并上传到服务器,再进行上面的测试,就会发现session不共享的问题完美解决。
-
安装Redis可参考 Centos7安装Redis5
-