java 發送POST、GET請求時,獲取請求的頭信息Set-Cookie,請求攜帶Cookie

需求背景

1、前端在請求時遇到跨域請求,連續的請求之間需要攜帶上一次的Cookie,前端不便於實現。
2、所以需要後端實現Cookie的獲取與請求攜帶,實現請求服務的代理請求。

可行性分析

1、 cookie (儲存在用戶本地終端上的數據)

Cookie 是在 HTTP 協議下,服務器或腳本可以維護客戶工作站上信息的一種方式。Cookie 是由 Web 服務器保存在用戶瀏覽器(客戶端)上的小文本文件,它可以包含有關用戶的信息。無論何時用戶鏈接到服務器,Web 站點都可以訪問 Cookie 信息。——百度百科

2、 瀏覽器怎麼處理cookie

  1. 服務器向瀏覽器設置cookie (http請求Set-Cookie字段)
    這裏寫圖片描述
  2. 瀏覽器向服務器提交cookie(http請求Cookie字段)
    這裏寫圖片描述

3、程序實現:通過http請求的信息獲取Set-Cookie的信息,然後再次提交時寫入Cookie信息就可實現。

程序流程

  1. 獲取需要代理的地址以及參數和請求方式。
  2. 獲取保存在Session中的Cookie信息寫入http請求頭信息(爲空則不寫入),根據請求的信息來發起http請求。
  3. 將獲取的http請求中的Set-Cookie的信息獲取Cookie,並將它保存到Session中。
  4. 返回代理的http請求返回的數據給前端。
    ( ps:步驟2是獲取上一次請求時步驟3設置的session )

程序代碼

1、請求工具類(請根據需要自行修改cookie名稱)

package func;

import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.commons.lang.StringUtils;

/**
 * 用於請求url數據
 * 每一次請求都要獲取Set-Cookie頭信息然後在使用的時候拼接請求寫入Cookie
 *
 * Cookie verCode 用與第二次請求時攜帶 
 * Cookie JSESSIONID 用於請求代理的SessionId(當前請求不返回)
 * 
 * @author yuyu
 *
 */
public class UrlLib {

    /**
     * 獲取Set-Cookie 寫入session中,然後請求在頭信息的時候寫入
     */
    public static byte[] doGet(HttpServletRequest request, String url, Map<String,String> param) throws Exception{
        //當傳入的url返回不爲空的時候,讀取數據
        InputStream  input=null;
        byte[] data = null;//提高字符數據的生成
        if(StringUtils.isNotBlank(url)){
            try{
                //設置請求的頭信息
                URL urlInfo = new URL(url+'?'+getParam(param));
                URLConnection connection = urlInfo.openConnection();
                connection.addRequestProperty("Host", urlInfo.getHost());//設置頭信息
                connection.addRequestProperty("Connection", "keep-alive");
                connection.addRequestProperty("Accept", "*/*");
                connection.addRequestProperty("Cookie", getSessionIncookie(request));//設置獲取的cookie
                connection.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64)");
                connection.connect();
                // 獲取所有響應頭字段
                getCookieToSession(request,connection);
                //獲取請求回來的信息
                input = connection.getInputStream();//定義返回數據的格式           
                data =  new byte[input.available()];
                input.read(data);

            }catch(Exception e){
                throw new Exception("讀取Url數據失敗:"+url,e);
            }finally {
                try{
                    input.close();
                }catch(Exception e){}
            }
        }
        return data;
    }

    /**
     * 獲取post請求 
     * @param request
     * @param string
     * @param param
     * @return
     */
    public static byte[] doPost(HttpServletRequest request, String url,
            Map<String, String> param) throws Exception{
        //當傳入的url返回不爲空的時候,讀取數據
        InputStream  input=null;
        PrintWriter out = null;
        byte[] data = null;//提高字符數據的生成
        if(StringUtils.isNotBlank(url)){
            try{
                //設置請求的頭信息
                URL urlInfo = new URL(url);
                URLConnection connection = urlInfo.openConnection();
                connection.addRequestProperty("Host", urlInfo.getHost());//設置頭信息
                connection.addRequestProperty("Connection", "keep-alive");
                connection.addRequestProperty("Accept", "*/*");
                connection.addRequestProperty("Cookie", getSessionIncookie(request));//設置獲取的cookie
                connection.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64)");
                // 發送POST請求必須設置如下兩行
                connection.setDoOutput(true);
                connection.setDoInput(true);
                // 獲取URLConnection對象對應的輸出流
                out = new PrintWriter(connection.getOutputStream());
                // 發送請求參數
                out.print(getParam(param));
                // flush輸出流的緩衝
                out.flush();
                // 獲取所有響應頭字段
                getCookieToSession(request,connection);
                //獲取請求回來的信息
                input = connection.getInputStream();//定義返回數據的格式           
                data =  new byte[input.available()];
                input.read(data);

            }catch(Exception e){
                throw new Exception("讀取Url數據失敗:"+url,e);
            }finally {
                try{
                    input.close();
                }catch(Exception e){}
            }
        }
        return data;
    }


    /**
     * 獲取在session中保存的cookie
     * @param request
     * @return
     */
    private static String getSessionIncookie(HttpServletRequest request) {
        String back="";
        HttpSession session = request.getSession();

        String  verCode=(String) session.getAttribute("verCode");
        String  JSESSIONID=(String) session.getAttribute("JSESSIONID");

        System.out.println(verCode);
        System.out.println(JSESSIONID);

        if(verCode!=null){
            back=verCode;
        }

        if(JSESSIONID!=null){
            if(!StringUtils.isEmpty(back)){
                back+=" ";
            }
            back+=JSESSIONID;
        }

        System.out.println(back);
        return back;
    }

    /**
     * 將請求的頭信息獲取到session中
     * @param request
     * @param connection
     */
    private static void getCookieToSession(HttpServletRequest request,
            URLConnection connection) {

        Map<String, List<String>> map = connection.getHeaderFields();
        for (String key : map.keySet()) {
            System.out.println(key + "--->" + map.get(key));
        }
        HttpSession session = request.getSession();

        List<String> cookie=map.get("Set-Cookie");
        if(cookie!=null){

            String verCode=getCookieBySet("verCode",cookie.get(0));

            String JSESSIONID=getCookieBySet("JSESSIONID",cookie.get(0));

            if(verCode!=null){
                session.setAttribute("verCode",verCode);
            }

            if(JSESSIONID!=null){
                session.setAttribute("JSESSIONID",JSESSIONID);
            }
        }

    }

    /**
     * 獲取verCode=b5pcogZaFGikpAc1mQ+G5wOJGBWtXLsHafpf5wlgF5s=; Path=/SSODAO/; HttpOnly
     * 的cookie信息
     */
    public static String getCookieBySet(String name,String set){

        String regex=name+"=(.*?);";

        Pattern pattern = Pattern.compile(regex);
        Matcher matcher =pattern.matcher(set);
        if(matcher.find()){
            return matcher.group();
        }
        return null;

    }

    /**
     * 將參數以 key=123&v=456 返回
     * @param param
     * @return
     */
    public static String getParam(Map<String,String> param){
        StringBuilder str=new StringBuilder();
        int size=0;
        for (Map.Entry<String, String> m :param.entrySet())  {
            str.append(m.getKey());
            str.append("=");
            str.append(m.getValue());
            if(size<param.size()-1){
                str.append("&");
            }
            size++;
        }
        System.out.println(str.toString());
        return str.toString();
    }

}

2、代理程序(servlet)

package testLogin;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import func.UrlLib;

@SuppressWarnings("serial")
public class LoginUrl extends HttpServlet {

    /**
    * 代理請求數據
    * 代理地址 http://127.0.0.1:8080/Test/servlet/
    *
    *   接口 TestOne
    *       參數 Time (String)
    *
    *   接口 TestTow
    *       接口 Code (String)
    *
    */
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        String base="http://127.0.0.1:8080/Test/servlet/";

        String url=request.getParameter("url");
        System.out.println(url);

        //第一次請求
        if("TestOne".equals(url)){
            String time=request.getParameter("Time");

            Map<String,String>  param= new HashMap<String, String>(); 
            param.put("Time", time);

            try {
                //請求圖片
                response.setContentType("image/jpeg");
                OutputStream out = response.getOutputStream();
                out.write(UrlLib.doGet(request, base+url, param));
                out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        //第二次請求
        }else if("TestTow".equals(url)){
            String code=request.getParameter("Code");
            Map<String,String>  param= new HashMap<String, String>(); 
            param.put("Code", code);

            try{
                //請求文字
                response.setContentType("text/html");
                PrintWriter out = response.getWriter();
                out.print(new String(UrlLib.doPost(request, base+url, param),"UTF-8"));
                out.flush();
                out.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }else{
            //參數錯誤
            response.setContentType("text/html");
            PrintWriter out = response.getWriter();
            out.print("參數錯誤");
            out.flush();
            out.close();
        }
    }

}

總結

  1. 給出的代碼示例時根據我的業務需求的代碼,具體使用的就是方法類中的doGet與doPost方法。
  2. 在cookie的獲取與設置中請根據需要修改cookie的名稱以獲取正確的cookie。
  3. JSESSIONID 的cookie在我測試中並未獲取到,原因是我請求的接口並沒有返回對應的Set-Cookie。
  4. 貼出請求的頭信息:
    null—>[HTTP/1.1 200]
    Date—>[Mon, 22 Jan 2018 01:01:14 GMT]
    Transfer-Encoding—>[chunked]
    Expires—>[Thu, 01 Jan 1970 00:00:00 GMT]
    Set-Cookie—>[verCode=+ifEGHWxioffSG6/7eQdmCwfRgLylaWmr0LOS0WCILM=; Path=/SSODAO/; HttpOnly]
    Connection—>[close]
    Content-Type—>[image/jpeg]
    Cache-Control—>[no-cache]
    Pragma—>[No-cache]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章