需求背景
1、前端在请求时遇到跨域请求,连续的请求之间需要携带上一次的Cookie,前端不便于实现。
2、所以需要后端实现Cookie的获取与请求携带,实现请求服务的代理请求。
可行性分析
1、 cookie (储存在用户本地终端上的数据)
2、 浏览器怎么处理cookie
- 服务器向浏览器设置cookie (http请求Set-Cookie字段)
- 浏览器向服务器提交cookie(http请求Cookie字段)
3、程序实现:通过http请求的信息获取Set-Cookie的信息,然后再次提交时写入Cookie信息就可实现。
程序流程
- 获取需要代理的地址以及参数和请求方式。
- 获取保存在Session中的Cookie信息写入http请求头信息(为空则不写入),根据请求的信息来发起http请求。
- 将获取的http请求中的Set-Cookie的信息获取Cookie,并将它保存到Session中。
- 返回代理的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();
}
}
}
总结
- 给出的代码示例时根据我的业务需求的代码,具体使用的就是方法类中的doGet与doPost方法。
- 在cookie的获取与设置中请根据需要修改cookie的名称以获取正确的cookie。
- JSESSIONID 的cookie在我测试中并未获取到,原因是我请求的接口并没有返回对应的Set-Cookie。
- 贴出请求的头信息:
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]