Cookie是啥
由于HTTP协议是无状态的,而服务器端的业务必须是要有状态的。Cookie诞生的最初目的是为了存储web中的状态信息,以方便服务器端使用。比如判断用户是否是第一次访问网站。目前最新的规范是RFC 6265,它是一个由浏览器服务器共同协作实现的规范。
客户端请求服务器之后,服务器通过Response的header携带Cookie,客户端保存在本地,下次请求的时候,在客户端request的header中携带这个Cookie
一个基本的Cookie结构如下
Set-Cookie: "name=value;domain=.domain.com;path=/;expires=Sat, 11 Jun 2016 11:29:42 GMT;HttpOnly;secure"
其中 name=value 是必选项,其它都是可选项。Cookie的主要构成如下:
name: 一个唯一确定的cookie名称。通常来讲cookie的名称是不区分大小写的。
value:存储在cookie中的字符串值。最好为cookie的name和value进行url编码
domain:cookie对于哪个域是有效的。所有向该域发送的请求中都会包含这个cookie信息。这个值可以包含子域(如:yq.aliyun.com),也可以不包含它(如:.aliyun.com,则对于aliyun.com的所有子域都有效).
path: 表示这个cookie影响到的路径,浏览器跟会根据这项配置,像指定域中匹配的路径发送cookie。
expires:失效时间,表示cookie何时应该被删除的时间戳(也就是,何时应该停止向服务器发送这个cookie)。如果不设置这个时间戳,浏览器会在页面关闭时即将删除所有cookie;不过也可以自己设置删除时间。这个值是GMT时间格式,如果客户端和服务器端时间不一致,使用expires就会存在偏差。
max-age: 与expires作用相同,用来告诉浏览器此cookie多久过期(单位是秒),而不是一个固定的时间点。正常情况下,max-age的优先级高于expires。
HttpOnly: 告知浏览器不允许通过脚本document.cookie去更改这个值,同样这个值在document.cookie中也不可见。但在http请求张仍然会携带这个cookie。注意这个值虽然在脚本中不可获取,但仍然在浏览器安装目录中以文件形式存在。这项设置通常在服务器端设置。
secure: 安全标志,指定后,只有在使用SSL链接时候才能发送到服务器,如果是http链接则不会传递该信息。就算设置了secure 属性也并不代表他人不能看到你机器本地保存的 cookie 信息,所以不要把重要信息放cookie就对了服务器端设置
如何通过拦截http请求拿到cookie
okhttp3天然支持获取cookie
只需要实现CookieJar
//拦截cookie
class LocalCookieJar implements CookieJar {
List<Cookie> cookies;
@Override
public List<Cookie> loadForRequest(HttpUrl url) {
if (cookies != null)
return cookies;
return new ArrayList<Cookie>();
}
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
this.cookies = cookies;
//存储当前cookie,用于webview中同步cookie
CookiesManager.getInstance().cookieMap.put(url,cookies)
}
}
并在okhttp的builder中添加cooloeJar
OkHttpClient mOkHttpClient = OkHttpUtils.newInstance().connectTimeout(45, TimeUnit.SECONDS)
.addInterceptor(new LogInterceptor())
.cookieJar(new LocalCookieJar(cookieHashMap))//添加cookie管理
.build();
在webview中同步cookie
以下代码在我项目中亲测有效,可能不同页面针对cookie参数设置不同,请根据自身项目来传所需要的cookie
webView.setWebViewClient(new CustomWebViewClient(mProgressWebView.getWebView()) {
/**
* 5.0以下
*/
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
synCookies(url);
return super.shouldInterceptRequest(view, url);//将加好cookie的url传给父类继续执行
}
/**
*5.0以上
*/
@SuppressLint("NewApi")
@Override
public WebResourceResponse shouldInterceptRequest(WebView view , WebResourceRequest request) {
String url = request.getUrl().toString();
synCookies(url);
return super.shouldInterceptRequest(view, url);
}
});
public static void synCookies(String url){
if ( !TextUtils.isEmpty(url) )
if (!null!=cookies ) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP){
CookieSyncManager.createInstance( context);
}
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie( true );
cookieManager.removeSessionCookie();// 移除
cookieManager.removeAllCookie();
for (Cookie cookie : cookies) {
StringBuilder sbCookie = new StringBuilder();//创建一个拼接cookie的容器,
sbCookie.append(cookie.name()+"="+cookie.value());
sbCookie.append(";domain="+cookie.domain());
sbCookie.append(";path="+cookie.path());
String cookieValue = sbCookie.toString();
cookieManager.setCookie(url, cookieValue);//为url设置cookie
}
CookieSyncManager.getInstance().sync();//同步cookie
String newCookie = cookieManager.getCookie(url); //这里可以查看当前设置进去的cookie
}
}