H5W3
当前位置:H5W3 > 其他技术问题 > 正文

UIWebView登陆需要记住用户名和密码下次自动登陆。(iOS UIWebView 通过 cookie 完成自动登录。)

现在我有个APP是嵌入的webView 登陆需要记住用户名和密码下次自动登陆,求大神看看如何实现?谢谢
目前这个问题我已经解决了,希望有用到的朋友来这里看http://www.jianshu.com/p/9bf9…:给颗心
另我把代码写到这里一份也:
1、在UIWebView的代理方法中实现获取cookies并将cookies放到NSUserDefaults保存起来

  - (void)webViewDidFinishLoad:(UIWebView*)webView{
    NSArray*nCookies = [[NSHTTPCookieStoragesharedHTTPCookieStorage]cookies];
    NSHTTPCookie*cookie;
    for(idcinnCookies)
    {
    if([cisKindOfClass:[NSHTTPCookieclass]])
    {
    cookie=(NSHTTPCookie*)c;
    if([cookie.nameisEqualToString:@"PHPSESSID"]) {
    NSNumber*sessionOnly = [NSNumbernumberWithBool:cookie.sessionOnly];
    NSNumber*isSecure = [NSNumbernumberWithBool:cookie.isSecure];
    NSArray*cookies = [NSArrayarrayWithObjects:cookie.name, cookie.value, sessionOnly, cookie.domain, cookie.path, isSecure,nil];
    [[NSUserDefaultsstandardUserDefaults]setObject:cookiesforKey:@"cookies"];
    break;
    }
    }
    }
    }

2、获取cookies:运行之后,UIWebview加载url之前获取保存好的cookies,并设置cookies,

NSArray*cookies =[[NSUserDefaultsstandardUserDefaults]objectForKey:@"cookies"];
NSMutableDictionary*cookieProperties = [NSMutableDictionarydictionary];
[cookiePropertiessetObject:[cookiesobjectAtIndex:0]forKey:NSHTTPCookieName];
[cookiePropertiessetObject:[cookiesobjectAtIndex:1]forKey:NSHTTPCookieValue];
[cookiePropertiessetObject:[cookiesobjectAtIndex:3]forKey:NSHTTPCookieDomain];
[cookiePropertiessetObject:[cookiesobjectAtIndex:4]forKey:NSHTTPCookiePath];
NSHTTPCookie*cookieuser = [NSHTTPCookiecookieWithProperties:cookieProperties];
[[NSHTTPCookieStoragesharedHTTPCookieStorage]setCookie:cookieuser];

注意:要在[self.webView loadRequest:req];之前设置获取cookies!

回答:

一般情况下登陆后希望记住登陆状态的实现并不是记住密码,因为这样是不安全的。我的做法是在cookie中保存登录状态,然后登录时将cookie传给app,app将这个cookie保存到本地,下一次访问网络的时候就带上这个cookie。
这里有两个主要的问题,

  1. 如何保存和读取cookie

  2. 如何访问网络时带上cookie
    因为中午了先睡个觉题主需要的话我晚一点回来补充


好了,我回来继续补充答案。
关于为什么能用cookie来保存登陆状态,这个是后台人员的事情,在这里暂且不介绍,题主需要的话自行查找相关资料。
这里以Java为例,提供一个简单的Demo,便于理解使用cookie
这个demo做了以下事情

  1. 向某个页面发起post请求。

  2. 设置了请求需要的一些参数,比如说字符集、Content-type、超时时间等等。

  3. 在请求中带上cookie(注意:首次请求cookie是空的,这一步在首次请求后,获取cookie后才有效果)

  4. connection.connect();后,使用connection.getHeaderField(“Set-Cookie”);就能获取服务器传过来的Cookie,注意,这里的cookie就是一个字符串而已。没什么特别的。

  5. 输出其他一些请求头的参数等等(这个主要是在调试的时候用的。)

这段代码可以直接在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<String, List<String>> headers = connection.getHeaderFields();

            for (Map.Entry<String, List<String>> 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 <Foundation/Foundation.h>

@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等等) ->保存表示,下一次打开应用的时候,读取表示,再次请求带上标识。就这么简单。 如果用户要退出登录,只要清除内存中和本地保存的表示就行了。

回答:

是否跟cookie有关

回答:

我现在也遇到这个问题“在qpp中嵌套webview需要保存账户和密码下次登录时不用再输入了”,楼主解决了吗?用的什么方法?如果有方法实现能不能给我发到邮箱 928284971@qq.com

回答:

没有必要这么做 ,也不要用cookie,webview里的单页面app是不能通过cookie来保持持久状态连接的,正确的做法应该是和后端去交换token ,检查token 是否过期 ,然后html5里面有一个重要的对象解决了web view里面持久化保存的问题:localstorage,localstorage 是一个类似于键值对的东西 保存在你的app 本地,你只要把你的用户信息以json 的方式存放到app里面,然后直接用js 去调用就可以了.举例 你第一次进来跳到登录页面以后 用户一旦登陆就把{username:’nickname’,sex:’male’,token:’yourtoken’}存放到localstorage的user 字段里,你下一次进webview 的时候只要去判断localstorage里的user字段是否为空,若不为空则取出user,然后每次和后端api请求都通过token,来判断 token 是否过期 如果过期则跳转到重新登录页面。这都是很标准的web app的标准做法。并且webview里的app建议使用angular或者react等框架和库来实现

本文地址:H5W3 » UIWebView登陆需要记住用户名和密码下次自动登陆。(iOS UIWebView 通过 cookie 完成自动登录。)

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址