1、Http協議html
1.1 什麼是http協議前端
http協議:對瀏覽器客戶端和服務器端之間數據傳輸的格式規範nginx
http無狀態協議:客戶端向服務器端發送請求,沒有事物管理。web
2、查看http協議的工具ajax
2.1 瀏覽器F12,進入開發者模式,點擊Network,刷新頁面便可查看請求apache
2.2 http協議格式分類json
請求(httpservletrequest對象)後端
請求行跨域
Request URL:https://www.baidu.com/img/baidu_jgylogo3.gif 請求地址瀏覽器
Request Method:GET 請求方式
請求頭
Accept:image/webp,image/apng,image/*,*/*;q=0.8 請求類型
Accept-Encoding:gzip, deflate, br 壓縮類型
Accept-Language:zh-CN,zh;q=0.9 請求編碼
Connection:keep-alive
Cookie:BAIDUID=3C5DBABB2234714F1860A4B6C35266D9:FG=1; PSTM=1554862563 cookie信息
Host:www.baidu.com 域名地址
Referer:https://www.baidu.com/ 代理類型
User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36 瀏覽器版本信息
請求內容 testMethod.html?name=eric&password=123456
請求體(post)name=eric&password=123456
響應(httpservletresponse對象)
請求行
響應內容
響應體(html查看元素)
2.3 請求行
2.3 .1協議版本
http1.0:當前瀏覽器客戶端與服務器端創建鏈接以後,只能發送一次請求,一次請求以後鏈接關閉。
http1.1:當前瀏覽器客戶端與服務器端創建鏈接以後,能夠在一次鏈接中發送屢次請求。(基本都使用1.1)
2.3 .2 請求資源
URL: 統一資源定位符。http://localhost:8080/day09/testImg.html。只能定位互聯網資源。是URI的子集。
URI:統一資源標記符。/day09/hello。用於標記任何資源。能夠是本地文件系統,局域網的資源(//192.168.14.10/myweb/index.html),能夠是互聯網。
2.3.3 請求方式
常見的請求方式: GET 、 POST、 HEAD、 TRACE、 PUT、 CONNECT 、DELETE
經常使用的請求方式: GET 和 POST
表單提交:
<form action="提交地址" method="GET/POST">
<form>
GET和POST的區別:
1)GET方式提交
a)地址欄(URI)會跟上參數數據。以?開頭,多個參數之間以&分割。
b)GET提交參數數據有限制,不超過1KB。
c)GET方式不適合提交敏感密碼。
d)注意:瀏覽器直接訪問的請求,默認提交方式是GET方式
GET /day09/testMethod.html?name=eric&password=123456 HTTP/1.1 Host: localhost:8080 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-cn,en-us;q=0.8,zh;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Referer: http://localhost:8080/day09/testMethod.html Connection: keep-alive |
2)POST方式提交
a)參數不會跟着URI後面。參數而是跟在請求的實體內容中。沒有?開頭,多個參數之間以&分割。
b)POST提交的參數數據沒有限制。
c)POST方式提交敏感數據。
POST /day09/testMethod.html HTTP/1.1 Host: localhost:8080 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-cn,en-us;q=0.8,zh;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Referer: http://localhost:8080/day09/testMethod.html Connection: keep-alive
name=eric&password=123456 |
2.4 請求頭
Accept: text/html,image/* -- 瀏覽器接受的數據類型 Accept-Charset: ISO-8859-1 -- 瀏覽器接受的編碼格式 Accept-Encoding: gzip,compress --瀏覽器接受的數據壓縮格式 Accept-Language: en-us,zh- --瀏覽器接受的語言 Host: www.it315.org:80 --(必須的)當前請求訪問的目標地址(主機:端口) If-Modified-Since: Tue, 11 Jul 2000 18:23:51 GMT --瀏覽器最後的緩存時間 Referer: http://www.it315.org/index.jsp -- 當前請求來自於哪裏 User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0) --瀏覽器類型 Cookie:name=eric -- 瀏覽器保存的cookie信息 Connection: close/Keep-Alive -- 瀏覽器跟服務器鏈接狀態。close: 鏈接關閉 keep-alive:保存鏈接。 Date: Tue, 11 Jul 2000 18:23:51 GMT -- 請求發出的時間 |
2.5 實體內容
只有POST提交的參數會放到實體內容中
2.6 HttpServletRequest對象
HttpServletRequest對象做用是用於獲取請求數據。
核心的API:
請求行:
request.getMethod(); 請求方式
request.getRequetURI() / request.getRequetURL() 請求資源
request.getProtocol() 請求http協議版本
請求頭:
request.getHeader("名稱") 根據請求頭獲取請求值
request.getHeaderNames() 獲取全部的請求頭名稱
實體內容:
request.getInputStream() 獲取實體內容數據
2.7 service和 doXX方法區別
先進入service方法,判斷req.getMethod(),在進入相近的doxxx方法
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); long lastModified; if (method.equals("GET")) { lastModified = this.getLastModified(req); if (lastModified == -1L) { this.doGet(req, resp); } else { long ifModifiedSince; try { ifModifiedSince = req.getDateHeader("If-Modified-Since"); } catch (IllegalArgumentException var9) { ifModifiedSince = -1L; } if (ifModifiedSince < lastModified / 1000L * 1000L) { this.maybeSetLastModified(resp, lastModified); this.doGet(req, resp); } else { resp.setStatus(304); } } } else if (method.equals("HEAD")) { lastModified = this.getLastModified(req); this.maybeSetLastModified(resp, lastModified); this.doHead(req, resp); } else if (method.equals("POST")) { this.doPost(req, resp); } else if (method.equals("PUT")) { this.doPut(req, resp); } else if (method.equals("DELETE")) { this.doDelete(req, resp); } else if (method.equals("OPTIONS")) { this.doOptions(req, resp); } else if (method.equals("TRACE")) { this.doTrace(req, resp); } else { String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[]{method}; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(501, errMsg); } }
2.8 時間戳
不少網站在發佈版本以前,都會在URL請求地址後面加上一個時間戳進行版本更新。
做用:防止緩存
2.9 防止非法連接(referer),防止盜鏈
網站的資源訪問時進行過濾,根據referer來判斷請求源頭決定是否給予訪問
配置web.xml
<filter> <filter-name>ImgFilter</filter-name> <filter-class>com.itmayiedu.filter.ImgFilter</filter-class> </filter> <filter-mapping> <filter-name>ImgFilter</filter-name> <url-pattern>/static/*</url-pattern> </filter-mapping>
後端代碼
publicclass ImgFilter implements Filter { publicvoid destroy() { } publicvoid doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; // 從請求來獲取referer String referer = request.getHeader("referer"); System.out.println("refer is" + "" + referer); // 判斷是否來自於非法盜鏈 if (referer == null || !referer.contains(request.getServerName())) { request.getRequestDispatcher("/static/error.png").forward(request, response); } else { filterChain.doFilter(request, response); } } publicvoid init(FilterConfig arg0) throws ServletException { } }
2.10 傳遞的請求參數如何獲取
GET方式:參數放在URI後面
POST方式:參數放在實體內容中
獲取GET方式參數:request.getQueryString();
獲取POST方式參數:request.getInputStream();
問題:可是以上兩種不通用,並且獲取到的參數還須要進一步地解析。因此可使用統一方便的獲取參數的方式:
request.getParameter("參數名"); 根據參數名獲取參數值(注意,只能獲取一個值的參數)
request.getParameterValue("參數名「);根據參數名獲取參數值(能夠獲取多個值的參數)
request.getParameterNames(); 獲取全部參數名稱列表
3、Http 響應
HTTP/1.1 200 OK --響應行 Server: Apache-Coyote/1.1 --響應頭(key-vaule) Content-Length: 24 Date: Fri, 30 Jan 2015 01:54:57 GMT --一個空行 this is hello servlet!!! --實體內容 |
3.1 響應行
3.1.1 狀態碼: 服務器處理請求的結果(狀態)
常見的狀態:
200 :表示請求處理完成並完美返回
302:表示請求須要進一步細化。
404:表示客戶訪問的資源找不到。
500:表示服務器的資源發送錯誤。(服務器內部錯誤)
3.1.2 常見的響應頭
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:保存鏈接 |
3.2 HttpServletResponse對象
HttpServletResponse對象修改響應信息:
響應行:
response.setStatus() 設置狀態碼
響應頭:
response.setHeader("name","value") 設置響應頭
實體內容:
response.getWriter().writer(); 發送字符實體內容
response.getOutputStream().writer() 發送字節實體內容
3.3 請求重定向(Location)
resp.setStatus(302); resp.setHeader("Location", "OtherServlet");
4、Https與Http
4.1 https與http區別
a、https 協議須要到 ca 申請證書,通常免費證書較少,於是須要必定費用。
b、http 是超文本傳輸協議,信息是明文傳輸,https 則是具備安全性的 ssl 加密傳輸協議。
c、http 和 https 使用的是徹底不一樣的鏈接方式,用的端口也不同,前者是 80,後者是 443。
d、http 的鏈接很簡單,是無狀態的;HTTPS 協議是由 SSL+HTTP 協議構建的可進行加密傳輸、身份認證的網絡協議,比 http 協議安全。
4.2 https工做原理
HTTPS 可以加密信息,以避免敏感信息被第三方獲取,因此不少銀行網站或電子郵箱等等安全級別較高的服務都會採用 HTTPS 協議。
客戶端在使用 HTTPS 方式與 Web 服務器通訊時有如下幾個步驟,如圖所示。
(1)客戶使用 https 的 URL 訪問 Web 服務器,要求與 Web 服務器創建 SSL 鏈接。
(2)Web 服務器收到客戶端請求後,會將網站的證書信息(證書中包含公鑰)傳送一份給客戶端。
(3)客戶端的瀏覽器與 Web 服務器開始協商 SSL 鏈接的安全等級,也就是信息加密的等級。
(4)客戶端的瀏覽器根據雙方贊成的安全等級,創建會話密鑰,而後利用網站的公鑰將會話密鑰加密,並傳送給網站。
(5)Web 服務器利用本身的私鑰解密出會話密鑰。
(6)Web 服務器利用會話密鑰加密與客戶端之間的通訊。
4.3 https優缺點
優勢:
HTTPS 可以加密信息,以避免敏感信息被第三方獲取
缺點:
(1)HTTPS 協議握手階段比較費時,會使頁面的加載時間延長近 50%,增長 10% 到 20% 的耗電;
(2)HTTPS 鏈接緩存不如 HTTP 高效,會增長數據開銷和功耗,甚至已有的安全措施也會所以而受到影響;
(3)SSL 證書須要錢,功能越強大的證書費用越高,我的網站、小網站沒有必要通常不會用。
(4)SSL 證書一般須要綁定 IP,不能在同一 IP 上綁定多個域名,IPv4 資源不可能支撐這個消耗。
(5)HTTPS 協議的加密範圍也比較有限,在黑客攻擊、拒絕服務攻擊、服務器劫持等方面幾乎起不到什麼做用。最關鍵的,SSL 證書的信用鏈體系並不安全,特別是在某些國家能夠控制 CA 根證書的狀況下,中間人攻擊同樣可行。
4.4 web安全與防攻擊
一、 什麼是xxs
實際上是腳本注入,使用過濾器將全部提交的參數的value值,轉換成html代碼執行
if (!StringUtils.isEmpty(value)) {
// 轉換Html
value = StringEscapeUtils.escapeHtml4(value);
}
二、 CSRF(模擬Http請求) 企業當中會有白名單和黑名單,底層是判斷請求源頭
三、 上傳漏洞
四、 SQL注入
五、 用一些HTTPS請求, 安全性高,走的ssl+證書,加密傳輸,非明文,可是效率低
5、http請求工具
5.1 客戶端模擬http請求工具
Postmen(谷歌插件)、RestClient
5.2 服務器端模擬http請求工具
httpclient、HttpURLConnection
httpCient請求代碼:
/** * 發送 post請求訪問本地應用並根據傳遞參數不一樣返回不一樣結果 */ publicvoid post() { // 建立默認的httpClient實例. CloseableHttpClient httpclient = HttpClients.createDefault(); // 建立httppost HttpPost httppost = new HttpPost("http://localhost:8080/myDemo/Ajax/serivceJ.action"); // 建立參數隊列 List<NameValuePair>formparams = new ArrayList<NameValuePair>(); formparams.add(new BasicNameValuePair("type", "house")); UrlEncodedFormEntity uefEntity; try { uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8"); httppost.setEntity(uefEntity); System.out.println("executing request " + httppost.getURI()); CloseableHttpResponse response = httpclient.execute(httppost); try { HttpEntity entity = response.getEntity(); if (entity != null) { System.out.println("--------------------------------------"); System.out.println("Response content: " + EntityUtils.toString(entity, "UTF-8")); System.out.println("--------------------------------------"); } } finally { response.close(); } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e1) { e1.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { // 關閉鏈接,釋放資源 try { httpclient.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 發送 get請求 */ publicvoid get() { CloseableHttpClient httpclient = HttpClients.createDefault(); try { // 建立httpget. HttpGet httpget = new HttpGet("http://www.baidu.com/"); System.out.println("executing request " + httpget.getURI()); // 執行get請求. CloseableHttpResponse response = httpclient.execute(httpget); try { // 獲取響應實體 HttpEntity entity = response.getEntity(); System.out.println("--------------------------------------"); // 打印響應狀態 System.out.println(response.getStatusLine()); if (entity != null) { // 打印響應內容長度 System.out.println("Response content length: " + entity.getContentLength()); // 打印響應內容 System.out.println("Response content: " + EntityUtils.toString(entity)); } System.out.println("------------------------------------"); } finally { response.close(); } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (ParseException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { // 關閉鏈接,釋放資源 try { httpclient.close(); } catch (IOException e) { e.printStackTrace(); } } }
5.3 前段ajax請求,ajax 異步操做,局部刷新。相似於後端的多線程技術
$.ajax({ type : 'post', dataType : "text", url : "http://a.a.com/a/FromUserServlet", data : "userName=張三&userAge=19", success : function(msg) { alert(msg); } });
5.4 跨域解決方案
跨域緣由產生:在當前域名請求網站中,默認不容許經過ajax請求發送其餘域名。
XMLHttpRequest cannot load跨域問題解決辦法
5.4.1 使用後臺response添加header
後臺response添加header,response.setHeader("Access-Control-Allow-Origin", "*");支持全部網站
寫到過濾器中,跨域問題統一處理
5.4.2 使用JSONP,(只支持get請求不支持post請求,開發較爲麻煩)
前端代碼:
$.ajax({ type : "POST", async : false, url : "http://a.a.com/a/FromUserServlet?userName=張三", dataType : "jsonp",//數據類型爲jsonp jsonp : "jsonpCallback",//服務端用於接收callback調用的function名的參數 success : function(data) { alert(data.result); }, error : function() { alert('fail'); } });
後端代碼:
@WebServlet("/FromUserServlet") publicclassFromUserServletextends HttpServlet { protectedvoid doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } protectedvoid doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setCharacterEncoding("UTF-8"); // resp.setHeader("Access-Control-Allow-Origin", "*"); String userName = req.getParameter("userName"); String userAge = req.getParameter("userAge"); System.out.println(userName + "----" + userAge+"---"+req.getMethod()); // JSONObject JSONObject1 = new JSONObject(); // JSONObject1.put("success", "添加成功!"); // resp.getWriter().write("callbackparam(" + JSONObject1.toJSONString() // + ")"); try { resp.setContentType("text/plain"); resp.setHeader("Pragma", "No-cache"); resp.setHeader("Cache-Control", "no-cache"); resp.setDateHeader("Expires", 0); PrintWriter out = resp.getWriter(); JSONObject resultJSON = new JSONObject(); // 根據須要拼裝json resultJSON.put("result", "content"); String jsonpCallback = req.getParameter("jsonpCallback");// 客戶端請求參數 out.println(jsonpCallback + "(" + resultJSON.toJSONString() + ")");// 返回jsonp格式數據 out.flush(); out.close(); } catch (Exception e) { } } }
jsonp會在瀏覽器生成一個get請求,帶上參數。
5.4.3 使用接口網關,使用nginx轉發
5.4.4 使用後臺服務轉發(不建議,佔用大量寬帶)