深刻理解Http協議

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 使用後臺服務轉發(不建議,佔用大量寬帶)

相關文章
相關標籤/搜索