怪我咯2017-04-17 17:34:114楼
一般情况下登陆后希望记住登陆状态的实现并不是记住密码,因为这样是不安全的。我的做法是在cookie中保存登录状态,然后登录时将cookie传给app,app将这个cookie保存到本地,下一次访问网络的时候就带上这个cookie。
这里有两个主要的问题,
如何保存和读取cookie
如何访问网络时带上cookie
因为中午了先睡个觉题主需要的话我晚一点回来补充
好了,我回来继续补充答案。
关于为什么能用cookie来保存登陆状态,这个是后台人员的事情,在这里暂且不介绍,题主需要的话自行查找相关资料。
这里以Java为例,提供一个简单的Demo,便于理解使用cookie
这个demo做了以下事情
向某个页面发起post请求。
设置了请求需要的一些参数,比如说字符集、Content-type、超时时间等等。
在请求中带上cookie(注意:首次请求cookie是空的,这一步在首次请求后,获取cookie后才有效果)
connection.connect();后,使用connection.getHeaderField("Set-Cookie");就能获取服务器传过来的Cookie,注意,这里的cookie就是一个字符串而已。没什么特别的。
输出其他一些请求头的参数等等(这个主要是在调试的时候用的。)
这段代码可以直接在android开发中使用。当然实际开发中我们并不会这么用,这是后话。
/**
* Created by cocbin on 2015/12/7.
*/
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;
public class main {
public static void main(String args[]) {
//向一个页面发起请求
String result = Post("http://test.com/");
System.out.println(result);
}
private static String KEY_CHARSET = "utf-8";
private static String cookie = "";
private static String Post(String murl) {
OutputStream outputStream = null;
OutputStreamWriter outputStreamWriter = null;
try {
URL url = new URL(murl);
URLConnection connection = url.openConnection();
connection.setDoOutput(true);
connection.setConnectTimeout(10000);
connection.setReadTimeout(10000);
connection.addRequestProperty("Content-type", "text/html");
//这里所谓请求的时候带上Cookie
connection.setRequestProperty("Cookie", cookie);
outputStream = connection.getOutputStream();
outputStreamWriter = new OutputStreamWriter(outputStream, KEY_CHARSET);
BufferedWriter bw = new BufferedWriter(outputStreamWriter);
bw.flush();
connection.connect();
//这里就是获得请求传过来的Cookie
if (connection.getHeaderField("Set-Cookie") != null) {
cookie = connection.getHeaderField("Set-Cookie");
}
System.out.println("cookie="+cookie);
Map> headers = connection.getHeaderFields();
for (Map.Entry> entry : headers.entrySet()) {
System.out.println(entry.getKey() + " : ");
for (String value : entry.getValue()) {
System.out.println(value + " , ");
}
}
System.out.println("----------");
System.out.println("getContentType: " + connection.getContentType());
System.out.println("getContentLength: " + connection.getContentLength());
System.out.println("getContentEncoding: " + connection.getContentEncoding());
System.out.println("getDate: " + connection.getDate());
System.out.println("getExpiration: " + connection.getExpiration());
System.out.println("getLastModifed: " + connection.getLastModified());
System.out.println("----------");
InputStream is = connection.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(is, KEY_CHARSET);
BufferedReader br = new BufferedReader(inputStreamReader);
String line = null;
StringBuffer result = new StringBuffer();
while ((line = br.readLine()) != null) {
result.append(line);
}
outputStream.close();
outputStreamWriter.close();
is.close();
inputStreamReader.close();
br.close();
return result.toString();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
通过上面这个post请求的代码,我们就能做到,每一次请求的cookie都是一致的了。也就是说,我们第一次向服务器发起请求时,cookie是空的,于是服务器给你生成一个cookie,传到客户端,客户端获取cookie(注意,这时候cookie是保存在内存里面的)。在此请求的时候,cookie里面是有值的,这个是通过connection.setRequestProperty("Cookie", cookie);传给服务器。这样子服务器就能够识别用户了。
当然,到了这里,cookie是保存在内存里面的,当程序退出后,内存里面保存的内容是会被清除的,所以,我们要想办法让他不清除,所以就要进行本地保存了。
我们前面提过,cookie只是个普通的字符串,没什么特别。
保存一个字符串而已这能难道到我们吗,大不了直接写个txt文件不就好了是吧。当然在移动开发中我们并不会这么做,因为移动平台给我们很好的api。
下面分别介绍android和ios的本地保存api。
Android
Android保存一般是使用SharedPreferences,保存的代码如下:( Global.context表示一个Context对象)
具体请自行搜索相关文档
SharedPreferences preferences =
Global.context.getSharedPreferences("PREFER_COOKIE", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putString("PREFER_COOKIE", cookie);
editor.apply();
然后是读取
SharedPreferences preferences =
Global.context.getSharedPreferences("PREFER_COOKIE", Context.MODE_PRIVATE);
cookie= preferences.getString("PREFER_COOKIE", "");
然后是清除(退出登录状态)
SharedPreferences preferences =
Global.context.getSharedPreferences("PREFER_COOKIE", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.clear().apply();
iOS
这里我封装了一个类,
头文件:
//
// CocCache.h
// caoaman
//
// Created by cocbin on 15/11/10.
// Copyright © 2015年 cocbin. All rights reserved.
//
#import
@interface CocCache : NSObject
+ (void)saveCache:(NSString *)key value:(NSString *)value;
+ (NSString *)getCache:(NSString *)key;
+ (void)clearCache:(NSString *)key;
@end
实现文件
//
// CocCache.m
// caoaman
//
// Created by cocbin on 15/11/10.
// Copyright © 2015年 cocbin. All rights reserved.
//
#import "CocCache.h"
@implementation CocCache
+ (void)saveCache:(NSString *)key value:(NSString *)value
{
NSUserDefaults * setting = [NSUserDefaults standardUserDefaults];
[setting setObject:value forKey:key];
[setting synchronize];
}
+ (NSString *)getCache:(NSString *)key
{
NSUserDefaults * settings = [NSUserDefaults standardUserDefaults];
NSString *value = [settings objectForKey:key];
return value;
}
+ (void)clearCache:(NSString *)key
{
NSUserDefaults * settings = [NSUserDefaults standardUserDefaults];
[settings removeObjectForKey:key];
[settings synchronize];
}
@end
具体用法看命名就知道了,就是普通的键值对保存。
最后是实现
好了,现在知道cookie是怎么回事了,也知道怎么本地保存了,接下来总结一下整个逻辑
首先打开应用
读取本地cookie(发现没有内容,表示未登录)
发起登陆请求
获取cookie
保存cookie到本地。
再次打开应用
读取本地cookie(存在一个字符串,还不能确定是否登陆)
带上cookie请求用户信息(能获取信息,表示用户登录了。这里需要后台提供一个获取用户信息的api)
在实际开发中,我们一般使用的网络框架是第三方框架,有些框架是自带保存cookie功能的。具体要看框架的文档了。
最后说一下,验证用户登录不一定是使用cookie,也可以用token或其他方式验证。这个就看后台怎么设计了。但是不管是cookie还是token,原理都是一样的。发起请求->获取标识(token或cookie等等) ->保存表示,下一次打开应用的时候,读取表示,再次请求带上标识。就这么简单。 如果用户要退出登录,只要清除内存中和本地保存的表示就行了。