HttpURLConnection之Cookie传递 2021-01-05

HttpURLConnection之Cookie传递

摘要:本文主要介绍使用HttpURLConnection访问Miracle系统Cookie传递相关技术要点

关键词:HttpURLConnection;CookieHandler;Session; Cookie;

 

  • 简介

我们知道HTTP协议是一种无状态协议,基于TCP/IP,即客户端请求服务器,服务器处理后,进行响应,这个过程是无状态的。

但是在有些时候需要保存一些客户端的请求信息,用以识别客户端的某些状态,有针对性的去保持某些客户端的习惯。这些时候,就需要去记录客户端的连接状态,识别请求的状态等。所以为了解决类似的事情,就需要使用到了 Cookie 和 Session。

以Miracle程序为例,使用Cookie的场景:记住用户名、记住密码的功能,当勾选这个的时候,下次进入该网站时,就会自动设置登录名或自动登录;使用Seesion的场景:利用Seesion来验证用户是否已登录。

         一般情况,使用浏览器作为客户端,访问Web程序,开发员无需过多关注Session和Cookie。但如果把客户端替换成HttpClient、HttpURLConnection或移动APP等其他应用程序,这就涉及到手工处理Cookie的问题。

         本文以HttpURLConnection为例,介绍如何实现Cookie的传递、接收。

 

  • HttpURLConnection介绍

HttpURLConnection提供了访问HTTP资源的一种方式,是Java的标准类,它继承自URLConnection,可用于向指定网站发送请求。它在URLConnection的基础上提供了如下便捷的方法:

int getResponseCode(); // 获取服务器的响应代码。

String getResponseMessage(); // 获取服务器的响应消息。

String getResponseMethod(); // 获取发送请求的方法。

void setRequestMethod(String method); // 设置发送请求的方法。

 

         使用HttpURLConnection访问HTTP资源一般范围如下六步:

1.使用java.net.URL封装个的HTTP资源url,并使用openConnection方法获得HttpURLConnection对象,代码如下:

URL url = new URL(targetUrl);

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

 

2.设置请求方法,例如GET、POST等,代码如下:

String method = "GET";

conn.setRequestMethod(method);

 

3.设置输入输出及其他权限。代码如下:

conn.setUseCaches(false);

conn.setDoOutput(true);

conn.setDoInput(true);

 

4.设置HTTP请求头。代码如下:

conn.setRequestProperty("Accept", "application/json, text/javascript");

conn.setRequestProperty("User-Agent", "Mozilla/5.0");

conn.setRequestProperty("Content-Type", "text/json;charset=UTF-8");

conn.setRequestProperty("Cache-Control", "no-cache");

 

5.输入输出数据。代码如下:

InputStream in = conn.getInputStream();

OutputStream out = conn.getOutputStream();

 

6.关闭输入和输出流。代码如下:

in.close();

out.close();

 

 

  • CookieHander的使用

作为HTTP协议处理器的一部分,J2SE5.0增加了CookieHandler来,用以管理Cookie。通过如下方式注册:

CookieManager cookieManager = new CookieManager();

CookieHandler.setDefault(cookieManager);

 

         注册完成后,发起HttpURLConnection连接,服务器端响应的Cookie信息就会保存到CookieManager中。响应完成后,可以通过如下方式获取Cookie:

CookieStore cookieStore = cookieManager.getCookieStore();

URI uri = getConnectUri(conn);

List<HttpCookie> httpCookies = cookieStore.get(uri);

 

         再次发起请求时,CookieHander会自动携带浏览器返回的Cookie信息,对于客户端设置的Cookie信息,如主题风格theme-skin,需要发起请求的时候,使用如下方式携带:

conn.setRequestProperty("Cookie", "theme-skin=metro-dark;");

 

 

  • 本地Cookie更新

HttpURLConnection响应完成后,服务端可能会删除某些Cookie。如退出登录后,会删除记住登录用户相关的Cookie。此时需更新本地Cookie信息,需要分两步。

第一步 ,将cookieManager中的Cookie更新或新增到本地。

CookieStore cookieStore = cookieManager.getCookieStore();

URI uri = getConnectUri(conn);

List<HttpCookie> httpCookies = cookieStore.get(uri);

 

// cookieStore中的cookie更新到浏览器

for (HttpCookie httpCookie : httpCookies) {

   String name = httpCookie.getName();

   if (KEY_JSESSIONID.equals(name)) continue;

 

   String value = httpCookie.getValue();

   // 查询浏览器中的Cookie

   Cookie cookie = getCookie(request, name);

   // Cookie不存在,则新增

   if (cookie == null) {

      Cookie newCookie = new Cookie(name, value);

      newCookie.setPath(cookiePath);

      response.addCookie(newCookie);

   }

   // Cookie存在,则更新

   else {

      cookie.setValue(httpCookie.getValue());

   }

}

 

         第二步,删除本地多余的Cookie

Cookie[] cookies = request.getCookies();

if (cookies != null) {

    for (Cookie cookie : cookies) {

       String name = cookie.getName();

       // 本地处理的Cookie过滤掉

       if ("login_remember_name".equals(name)) continue;

       if ("lang".equals(name)) continue;

 

       HttpCookie httpCookie = getHttpCookie(httpCookies, name);

       if (httpCookie == null || httpCookie.getMaxAge() == 0) {

           cancelCookie(request, response, name);

       }

    }

}

 

         删除本地Cookie(以浏览器为例)的方法如下:

void cancelCookie(HttpServletRequest request, HttpServletResponse response, String cookieName) {

     Cookie cookie = new Cookie(cookieName, null);

     cookie.setMaxAge(0);

     cookie.setPath(getCookiePath(request));

     response.addCookie(cookie);

}

 

String getCookiePath(HttpServletRequest request) {

     String contextPath = request.getContextPath();

     return contextPath.length() > 0 ? contextPath : "/";

}

 

         至此,HttpURLConnection使用CookieHander进行Cookie传输与更新的技术要点已经总结完毕。

 

 

  • 总结

通过使用过CookieHander进行Cookie传输,我们完全可以通过Java模拟类似Nginx反向代理,浏览器请求代理服务器,代理服务器做好Cookie传输,对应响应内容,根据实际业务需要定制处理。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
package test; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.List; import java.util.Map; public class HttpTest { private HttpURLConnection hc = null; private static final String oneUrlString = "http://xxx.jsp"; private static final String twoUrlString = "http://xxx.action"; public String getSessionId() { String sessionId = ""; try { URL url = new URL(oneUrlString); hc = (HttpURLConnection) url.openConnection();//默认的用GET提交 hc.setDoOutput(true); hc.connect(); Map map = hc.getHeaderFields(); //得到Cookie的所有内容,包括SESSIONID,在进行下次提交的时候 直接把这个Cookie的值设到头里头就行了 //淡然只得到SESSIONID也很简单的 ,但是有时候Set-Cookie的值有几个的 List list = (List) map.get("Set-Cookie"); if(list.size() == 0||list == null) { return null; } StringBuilder builder = new StringBuilder(); for(String str : list) { sessionId = builder.append(str).toString(); } hc.disconnect(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return sessionId; } public String getResponseContext(String parameters) { String responseContext = ""; try { URL url = new URL(twoUrlString); hc = (HttpURLConnection) url.openConnection();//使用POST提交 hc.addRequestProperty("Cookie", getSessionId()); hc.setDoOutput(true); hc.connect(); OutputStream out = hc.getOutputStream(); //参数是a=""&b=""这样拼接的一个串 out.flush(); out.close(); out.write(parameters.getBytes(),0,parameters.getBytes().length); InputStream in = hc.getInputStream(); InputStreamReader reader = new InputStreamReader(in,"gb2312"); BufferedReader read = new BufferedReader(reader); StringBuilder builder = new StringBuilder(); String str = ""; while((str = read.readLine()) != null) { builder = builder.append(str); } read.close(); reader.close(); in.close(); hc.disconnect(); responseContext = builder.toString(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return responseContext; } }
Java中使用HttpURLConnection上传文件需要以下步骤: 1. 创建URL对象 ```java URL url = new URL(uploadUrl); ``` 2. 创建HttpURLConnection对象 ```java HttpURLConnection conn = (HttpURLConnection) url.openConnection(); ``` 3. 设置请求方式为POST,设置其他请求头参数 ```java conn.setRequestMethod("POST"); conn.setDoOutput(true); conn.setDoInput(true); conn.setUseCaches(false); conn.setRequestProperty("Charset", "UTF-8"); conn.setRequestProperty("Connection", "Keep-Alive"); conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); ``` 4. 创建输出流并将数据写入输出流 ```java DataOutputStream outputStream = new DataOutputStream(conn.getOutputStream()); outputStream.writeBytes("--" + BOUNDARY + "\r\n"); outputStream.writeBytes("Content-Disposition: form-data; name=\"file\"; filename=\"" + file.getName() + "\"\r\n"); outputStream.writeBytes("\r\n"); FileInputStream fileInputStream = new FileInputStream(file); byte[] buffer = new byte[1024]; int len; while ((len = fileInputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, len); } outputStream.writeBytes("\r\n--" + BOUNDARY + "--\r\n"); ``` 5. 获取响应结果 ```java InputStream inputStream = conn.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); String line; StringBuilder result = new StringBuilder(); while ((line = reader.readLine()) != null) { result.append(line); } ``` 完整的代码示例: ```java public static void uploadFile(File file, String uploadUrl) throws Exception { String BOUNDARY = "---------------------------123821742118716"; URL url = new URL(uploadUrl); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setDoOutput(true); conn.setDoInput(true); conn.setUseCaches(false); conn.setRequestProperty("Charset", "UTF-8"); conn.setRequestProperty("Connection", "Keep-Alive"); conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); DataOutputStream outputStream = new DataOutputStream(conn.getOutputStream()); outputStream.writeBytes("--" + BOUNDARY + "\r\n"); outputStream.writeBytes("Content-Disposition: form-data; name=\"file\"; filename=\"" + file.getName() + "\"\r\n"); outputStream.writeBytes("\r\n"); FileInputStream fileInputStream = new FileInputStream(file); byte[] buffer = new byte[1024]; int len; while ((len = fileInputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, len); } outputStream.writeBytes("\r\n--" + BOUNDARY + "--\r\n"); InputStream inputStream = conn.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); String line; StringBuilder result = new StringBuilder(); while ((line = reader.readLine()) != null) { result.append(line); } outputStream.close(); fileInputStream.close(); inputStream.close(); conn.disconnect(); } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值