Cookie,有时也用其复数形式Cookies,指某些网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(通常经过加密)。
Cookie是由服务器端生成,发送给User-Agent(一般是浏览器,客户端),浏览器会将Cookie的key/value保存到某个目录下的文本文件内,下次请求同一网站时就发送该Cookie给服务器(前提是浏览器设置为启用cookie)。Cookie名称和值可以由服务器端开发自己定义,对于JSP而言也可以直接写入jsessionid,这样服务器可以知道该用户是否合法用户以及是否需要重新登录等。
Android 中Cookie 的操作:
逻辑:Cookie是由服务器生成的。客户端第一次向服务器发送Http请求时,由于没有Cookie,在Http请求头中即Header中不包含”Cookie”。此时在服务器返回的相应(HttpResponse)中会多一个字段”Set-Cookie”,此字段的值就是服务器生成的Cookie值,下次再由此客户端程序访问该服务器时,就可以把该Cookie值放入Http请求头中。服务器就会知道是哪个用户再次访问了该服务器。客户端需要保存该Cookie以此用户再次访问服务器时使用。Cookie会有一个失效时间,客户端在Cookie失效后再次访问服务器,服务器会返回一个Cookie失效的状态码(比如403之类的),并在HttpResponse中包含”Set-Cookie”字段,这里面是新的Cookie。客户端需要做的操作是:1.将新Cookie覆盖旧的Cookie。2.跳入用户登录界面,让用户用新的Cookie重新登陆。Cookie 可以保存在SharePreferenced或者Sqlite中。
正式进入今天的所说的内容,下面试通过使用鸿洋大神写的okhttp的辅助工具类okhttputils来说说cookie的使用。
为啥要用cookie?
大家都知道http连接是无状态的,从Android客户端登录服务端,客户端如果没有任何操作记录cookie,以便访问数据时,带过去请求服务端,那服务端会视为非法用户,无法获取数据。有人说,那就用userid去访问就行了,如果是这样的操作,用抓包工具就可以轻易地获取到你服务端的数据,这对一些敏感的数据来说,这是致命。所以就需要使用cookie与token去实现相对安全一点的获取数据了。
在开发app中会遇到一些困惑,IOS通过http去访问的时候,不用任何操作,服务器都能识别保留了从IOS端访问的cookie,而Android不能,需要自己去保存cookie,访问的时候带过去给服务端。具体的原因,暂时不太清楚,可能是iOS在http中做了啥操作,希望知道的朋友可以告诉我一下。
如何使用okhttputils中cookie?
在Android studio中如何下载okhttp与okhttputils,在这就不多说了,参考鸿洋大神的 https://github.com/hongyangAndroid/okhttputils
首先在Application中配置一下
@Override
public void onCreate() {
super.onCreate();
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(10000L, TimeUnit.MILLISECONDS)
.readTimeout(10000L, TimeUnit.MILLISECONDS)
.addInterceptor(new LoggerInterceptor("TAG"))
.cookieJar(new CookieJarImpl(new PersistentCookieStore(getApplicationContext()))) //要在内存Cookie前
.cookieJar(new CookieJarImpl(new MemoryCookieStore()))//内存Cookie
.build();
OkHttpUtils.initClient(okHttpClient);
}
ps:这里就已经集合cookie了,以后的cookie就会自动管理的了,这个还是比较节省时间的。
具体的用法
/**
* 登录
*/
private void login() {
OkHttpUtils
.post()
.url("http://192.168.2.37/wawa1/index.php/wap/login/index")
.addParams("account", "18819283512")
.addParams("pass", "123456")
.build()
.execute(new StringCallback() {
@Override
public void onError(Call call, Exception e, int id) {
Log.i(TAG, "onError: " + e.toString());
}
@Override
public void onResponse(String response, int id) {
if (!response.isEmpty()) {
try {
JSONObject jsonObject = new JSONObject(response);
if ("success".equals(jsonObject.getString("result"))) {
Log.i(TAG, "登录成功");
Log.i(TAG, "tokens: " + jsonObject.getString("tokens"));
token = jsonObject.getString("tokens");
} else {
Log.i(TAG, "登录失败");
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
});
}
/**
* 获取数据
*/
private void getdata() {
OkHttpUtils
.get()
.url("http://192.168.2.37/wawa1/index.php/wap/index/index")
.addParams("creature", "niu")
.addParams("ken", token)
.build()
.execute(new StringCallback() {
@Override
public void onError(Call call, Exception e, int id) {
Log.i(TAG, "onError: " + e.toString());
}
@Override
public void onResponse(String response, int id) {
if (!response.isEmpty()) {
try {
JSONObject jsonObject = new JSONObject(response);
if ("success".equals(jsonObject.getString("result"))) {
Log.i(TAG, "获取成功");
tvInfo.setText(response);
} else {
Log.i(TAG, "获取失败");
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
});
}
这里就已经实现了,用户登录后,直接通过cookie与token去访问服务端,获取数据就ok了,不再需要传userid了。也不需要和后台人员争吵了,因为ios行,Android不行,总是会争吵的,这样就能解决了。 不过这里还是有个问题,配置了持久化cookie中PersistentCookieStore,但是真正用起来还不行的,用户杀死了进程,再进来好像cookie失效了,暂时无法知道服务端问题还是本地这个cookie的问题,希望知道的朋友,可以告知一下,谢谢。
最后看看效果图: