CEF3开发者系列之Cookies管理和共享<转>
原帖地址:https://www.cnblogs.com/guolixiucai/p/6994559.html
涉及网页登录相关的技术,Cookies肯定是忽略不了的。由于项目的需要,要做一个双核的产品。双核间切换会涉及到登录状态的问题,共享Cookies是一个很好的方案。既然涉及到共享cookies,那么读取完整的cookies和设置cookies就是问题的关键。由于应用本身只需要加载自家的平台,不用考虑共享所有网站cookie的问题,所以需要获取的和设置的cookies相对比较简单。
IE浏览器内核Cookies的获取和设置相对难一点,但是好在网络上资料比较多。Chromium内核基于CEF3框架,获取和设置cookies有现成的接口。在这里主要总结的是IE浏览器内核Cookies的获取和基于CEF3框架的Cookies设置以及获取。
IE浏览器内核的Cookies获取的三种方式:
1、通过读取存在硬盘上的cookies文件,来获取指定网站的cookies;
2、通过用MSHTMLI的Dispatch接口IWebBrowser2和IHTMLDocument2来获取cookies;
3、通过API函数InternetGetCookieEx和InternetGetCookie来获取cookies;
4、通过Hook WINNET 相关的函数获取Cookies,HOOK住发送和接收包API(send、recv、WSASend、WSARecv等)。然后分析HTTP header。此处不讲。
第一种方式,实现起来比较笨重,一般作为后边两种方式的补充。实现代码如下:
std::wstring GetCookiesUnderIE7( wstring strDomain )
{
wstring strCookiePath;
TCHAR dataPath[MAX_PATH];
::SHGetSpecialFolderPath(NULL, dataPath, CSIDL_COOKIES, FALSE);
strCookiePath = dataPath; TCHAR szUserName[];
DWORD cbUserName;
cbUserName = ;
GetUserName(szUserName, &cbUserName);
WIN32_FIND_DATA FindData;
HANDLE hfile;
DWORD errorcode = ;
hfile = FindFirstFile((strCookiePath + L"\\*.txt").c_str() ,&FindData);
wstring wsUserName = szUserName;
wstring wsCookieName = wsUserName + L"@xx"; //xx为网站域名,如百度的baidu
wstring wsFileName;
wstring wsCookies = L"";
hile(hfile!= INVALID_HANDLE_VALUE && errorcode != ERROR_NO_MORE_FILES)
{
wsFileName = FindData.cFileName;
//判断是否存在【user】@xx为名称的cookie脚本,提高过滤效率
if (wsFileName.find(wsCookieName.c_str()) != wstring::npos)
{
wsFileName = strCookiePath + L"\\"+ FindData.cFileName;
//http://www.cnblogs.com/guolixiucai/;
std::ifstream ifsCookie(wsFileName.c_str(), std::ios::in | std::ios::binary);
if (ifsCookie)
{
std::string contents;
ifsCookie.seekg(, std::ios::end);
contents.resize(ifsCookie.tellg());
ifsCookie.seekg(, std::ios::beg);
ifsCookie.read(&contents[], contents.size());
if(contents.find("ispass_37wan_com") != string::npos)
{
wsCookies = s2ws(contents);
ifsCookie.close();
break;
}
ifsCookie.close();
}
} BOOL flag = TRUE;
BOOL isNextFile = FindNextFile(hfile,&FindData);//判断该目录下是否还有文件
if(flag == TRUE && isNextFile == TRUE)//如果还有文件,则调用SetLastError,设为NO_ERROR,这样才能继续遍历后面的文件
SetLastError(NO_ERROR);
else
errorcode=GetLastError();
}
return wsCookies;
}
第二种方式获取的Cookies并不完全,只能获取到部分Cookies
IHTMLDocument2::get_cookie()
IHTMLDocument2::put_cookie()
用MSHTML对Document对象的Cookie属性进行操作。也可以实现类似InternetGetCookie和InternetSetCookie的效果。实际上它等同于用javascript来读写文档中的Cookie。它同样可以获取、添加、覆盖、修改、删除持久Cookie和会话级Cookie,但不可读写HTTPOnly的Cookie。这种方式同样也要十分注意设置的Cookie的每个属性都要和目标Cookie一一对应才能正确操作Cookie。特别是Path和Domain属性,否则会导致添加了一个同名Cookie而不能覆盖或清除目标Cookie的结果。
代码如下:
std::wstring BrowserView::GetCookies()
{
CComPtr<IWebBrowser2> webBrowser;
HRESULT hr = QueryControl(IID_IWebBrowser2,
reinterpret_cast<void**>(&webBrowser));
if (FAILED(hr) || (!webBrowser))
return L""; CComPtr<IDispatch> disp;
hr = webBrowser->get_Document(&disp);
if (FAILED(hr) || (!disp))
return L""; CComPtr<IHTMLDocument2> document;
hr = disp->QueryInterface(IID_IHTMLDocument2,
reinterpret_cast<void**>(&document));
if (FAILED(hr) || (!document))
return L""; BSTR bstrCookie;
hr = document->get_cookie(&bstrCookie);
BSTR bstrDomain;
document->get_domain(&bstrDomain);
if (FAILED(hr))
{
return L"";
}
wstring strCookie(bstrCookie);
char* lpszText2 = _com_util::ConvertBSTRToString(bstrCookie);
SysFreeString(bstrCookie);
return strCookie;
}
第三种方式:
InternetGetCookie
InternetSetCookie
InternetGetCookieEx
InternetSetCookieEx
这些API属于Wininet,可以获取、添加、覆盖、修改、删除持久Cookie和会话级Cookie(会话级Cookie需要在同进程中操作)。加Ex后缀的API可以对HTTPOnly的Cookie进行操作。但这组API对IE7及以下的IE浏览器内核无效,取不到Cookies,这时候就需要使用第一种方法补充。当然也可以使用其他比较复杂的方法,例如Hook WINNET 相关的函数。
std::wstring GetCookies( wstring strDomain )
{
LPDWORD lpdwSize = new DWORD;
wchar_t strCookie[] = {};
int size = ;
//InternetGetCookie 取不到httponly的cookie,留在这里仅供后来者参考
// InternetGetCookie(strDomain.c_str(), NULL, NULL, lpdwSize);
// InternetGetCookie(strDomain.c_str(), NULL, strCookie, lpdwSize/*, INTERNET_COOKIE_HTTPONLY, NULL*/); //InternetGetCookieEx 在IE7和IE6里也是取不全cookie。
InternetGetCookieEx(strDomain.c_str(), NULL, strCookie, lpdwSize, 0x2000, NULL);
wstring wsCookies = strCookie;
return wsCookies;
}
CEF3中Cookies的管理。
如果不想听我啰嗦,移步http://magpcss.org/ceforum/apidocs3/projects/(default)/CefCookieManager.html
下边的内容基本上是翻译这个文档,在加上两个实例。
CEF3中,CefCookieManager这个类就是用来管理cookies的。在头文件cef_cookies中,在cef_cookies_capi.h里,有详细的注释,和上边链接里的文档说明一样。
Cookies的管理无外乎Cookies的设置、获取、删除、查找,外加一个存储位置的设置。
class CefCookieManager
extends CefBase
Class used for managing cookies. The methods of this class may be called on any thread unless otherwise indicated.
该类用来管理cookies。除非另有说明,该类的方法可以在任何线程中调用
Method Summary | |
static CefRefPtr< CefCookieManager > |
CreateManager( const CefString& path, bool persist_session_cookies, CefRefPtr< CefCompletionCallback > callback ) Creates a new cookie manager. |
virtual bool |
DeleteCookies( const CefString& url, const CefString& cookie_name, CefRefPtr< CefDeleteCookiesCallback > callback )= 0 Delete all cookies that match the specified parameters. |
virtual bool |
FlushStore( CefRefPtr< CefCompletionCallback > callback )= 0 Flush the backing store (if any) to disk. |
static CefRefPtr< CefCookieManager > |
GetGlobalManager( CefRefPtr< CefCompletionCallback > callback ) Returns the global cookie manager. |
virtual bool |
SetCookie( const CefString& url, const CefCookie& cookie, CefRefPtr< CefSetCookieCallback > callback )= 0 Sets a cookie given a valid URL and explicit user-provided cookie attributes. |
virtual bool |
SetStoragePath( const CefString& path, bool persist_session_cookies, CefRefPtr< CefCompletionCallback > callback )= 0 Sets the directory path that will be used for storing cookie data. |
virtual void |
SetSupportedSchemes( const std::vector< CefString >& schemes, CefRefPtr< CefCompletionCallback > callback )= 0 Set the schemes supported by this manager. |
virtual bool |
VisitAllCookies( CefRefPtr< CefCookieVisitor > visitor )= 0 Visit all cookies on the IO thread. |
virtual bool |
VisitUrlCookies( const CefString& url, bool includeHttpOnly, CefRefPtr< CefCookieVisitor > visitor )= 0 Visit a subset of cookies on the IO thread. |
Method Detail
CreateManager
public static CefRefPtr< CefCookieManager > CreateManager( const CefString& path, bool persist_session_cookies, CefRefPtr< CefCompletionCallback > callback );
创建一个新的cookie管理器,当|path|没有被设置时,数据存储在内存中。否则,数据保存在指定的|path|(如果在cef初始化时,指定了缓存路径,那么cookies会保存在此路径)。持久化会话cookies(没有有效期或有效区域),需要设置|persist_session_cookies| 为true。会话cookies一般是暂时性的并且大多数浏览器并不支持。如果|callback| 为 non-NULL ,那么在管理器存储空间初始化后,会在IO线程中异步执行。
DeleteCookies
public virtual bool DeleteCookies( const CefString& url, const CefString& cookie_name, CefRefPtr< CefDeleteCookiesCallback > callback )= 0;
删除与指定参数的相匹配的所有cookies。如果 |url| 和 |cookie_name| 都被指定,那么 host和domian与这两个参数匹配的都被删除。如果 |url|为空,那么所有的hosts 和domains的cookies都没清空。如果|callback| 为 non-NULL ,那么在cookies被删除后,该回调函数会在IO线程中异步执行。如果不存在指定的url或者cookies不能被访问,那么返回falsh。cookies可以通过交替使用Visit*Cookies()方法被删除。
//向指定的域名删除cookies
void ClientAppBrowser::DeleteCookies( std::wstring domain, std::wstring cookiename )
{
CefRefPtr<CefCookieManager> manager = CefCookieManager::GetGlobalManager(NULL);
DCHECK(manager.get());
CefRefPtr<CefDeleteCookiesCallback> callback = NULL;
std::wstring httpDomain = domain;
CefString cookie_name;
cookie_name.FromWString(cookiename .c_str());
base::IgnoreResult(&CefCookieManager::DeleteCookies);
CefPostTask(TID_IO, NewCefRunnableMethod(manager.get(), &CefCookieManager::DeleteCookies,
CefString(httpDomain.c_str()), cookie_name, callback));
}
FlushStore
public virtual bool FlushStore( CefRefPtr< CefCompletionCallback > callback )= 0;
将备份存储(如果存在)缓存到硬盘,如果|callback| 为 non-NULL ,在缓存完后,该回调函数会在IO线程中异步执行。cookies不能被访问则返回falsh。
GetGlobalManager
public static CefRefPtr< CefCookieManager > GetGlobalManager( CefRefPtr< CefCompletionCallback > callback );
返回全局cookie管理器,默认存储路径是 CefSettings.cache_path或者其他指定路径,否则存储在内存。如果|callback| 为 non-NULL ,在管理器存储空间初始化后,该回调函数会在IO线程中异步执行。该方法与调用CefRequestContext::GetGlobalContext()->GetDefaultCookieManager()相当
SetCookie
public virtual bool SetCookie( const CefString& url, const CefCookie& cookie, CefRefPtr< CefSetCookieCallback > callback )= 0;
设置一个指定了url和由用户设置了属性的cookie。该方法需要每个属性有符合良好的格式。检查非法字符(例如“;”存在cookie属性值中),存在非法字符会导致cookies设置失败。如果|callback| 为 non-NULL ,那么在cookies被设置后,该回调函数会在IO线程中异步执行。指定的url不存在或者cookies不能被访问,返回falsh。
实例
void ClientAppBrowser::SetCookies( std::wstring domain, std::wstring key, std::wstring svalue )
{
/*
向指定的域名写Cookie http://www.cnblogs.com/guolixiucai/
*/
CefRefPtr<CefCookieManager> manager = CefCookieManager::GetGlobalManager(NULL);
DCHECK(manager.get());
CefRefPtr<CefSetCookieCallback> callback = NULL;
CefCookie cookie;
CefString(&cookie.name).FromWString(key.c_str());
CefString(&cookie.value).FromWString(svalue.c_str());
CefString(&cookie.domain).FromWString(domain.c_str());
CefString(&cookie.path).FromASCII("/");
cookie.has_expires = true;
//以下过期时间随意设置的。
cookie.expires.year = ;
cookie.expires.month = ;
cookie.expires.day_of_week = ;
cookie.expires.day_of_month = ;
std::wstring httpDomain = L"http://www";
httpDomain.append(domain);
base::IgnoreResult(&CefCookieManager::SetCookie);
CefPostTask(TID_IO, NewCefRunnableMethod(manager.get(), &CefCookieManager::SetCookie,
CefString(httpDomain.c_str()), cookie, callback));
}
SetStoragePath
public virtual bool SetStoragePath( const CefString& path, bool persist_session_cookies, CefRefPtr< CefCompletionCallback > callback )= 0;
设置存储cookies数据的路径。如果|path|为空,则存储在内存中。持久化会话cookies(没有有效期或有效区域),需要设置|persist_session_cookies| 为true。会话cookies一般是暂时性的并且大多数浏览器并不支持。如果|callback| 为 non-NULL ,那么在管理器存储空间初始化后,会在IO线程中异步执行。
SetSupportedSchemes
public virtual void SetSupportedSchemes( const std::vector< CefString >& schemes, CefRefPtr< CefCompletionCallback > callback )= 0;
设置管理器支持的协议。支持常见的协议("http", "https", "ws" and "wss")。如果|callback| 为 non-NULL ,在协议更改生效后,该回调函数会在IO线程中异步执行。该方法必须在所有cookies被访问前调用
VisitAllCookies
public virtual bool VisitAllCookies( CefRefPtr< CefCookieVisitor > visitor )= 0;
访问IO线程中所有的Cookies。返回的cookies按照最长路径排序,然后再按照最长创建时间排序。如果cookies被占用则返回false。
VisitUrlCookies
public virtual bool VisitUrlCookies( const CefString& url, bool includeHttpOnly, CefRefPtr< CefCookieVisitor > visitor )= 0;
访问IO线程上的一组Cookie。返回结果可按照url、host、domain和路径过滤。如果|includeHttpOnly|为ture,那么结果中还会包含HTTP-only cookies。返回的cookies按照最长路径排序,然后再按照最长创建时间排序。如果cookies被占用则返回false。
原帖地址:https://www.cnblogs.com/guolixiucai/p/6994559.html
CEF3开发者系列之Cookies管理和共享<转>的更多相关文章
- CEF3开发者系列之Cookies管理和共享
涉及网页登录相关的技术,Cookies肯定是忽略不了的.由于项目的需要,要做一个双核的产品.双核间切换会涉及到登录状态的问题,共享Cookies是一个很好的方案.既然涉及到共享cookies,那么读取 ...
- CEF3开发者系列之进程和线程
CEF3是一个多进程架构框架,如果有了解过chromium的进程架构的,那么就很容易了解CEF3的多进程了.打开CEF3源代码中发布的cefclient实例,如果打开的页面带有flash或者其他插件. ...
- CEF3开发者系列之类和接口
CEF3基本的框架包含C/C++程 序接口,通过本地库的接口来实现,而这个库则会隔离宿主程序和 Chromium&Webkit的操作细节.它在浏览器控件和宿主程序之间提供紧密的整合,它支持用户 ...
- CEF3开发者系列之工程和代码结构
CEF支持一系列的编程语言和操作系统,并且能很容易地整合到新的或已有的工程中去.它的设计思想就是易用且兼顾性能. CEF3支持一系列的编程语言和操作系统,并且能很容易地整合到新的或已有的工程中去.它的 ...
- CEF3开发者系列之CEF3入门
CEF全称Chromium Embedded Framework,是一个基于Google Chromium 的开源项目.Google Chromium项目主要是为Google Chrome应用开发的, ...
- CEF3开发者系列之外篇——IE中JS与C++交互
使用IE内核开发客户端产品,系统和前端页面之间的交互,通常给开发和维护带来很大的便利性.但操作系统和前端之间的交互却是比较复杂的.具体来说就是脚本语言和编译语言的交互.在IE内核中html和css虽然 ...
- CEF3开发者系列之JS与C++交互之二
本文翻译自JavaScriptIntegration (https://bitbucket.org/chromiumembedded/cef/wiki/JavaScriptIntegration).本 ...
- CEF3开发者系列之JS与C++交互之一
JS与Native交互是相对于比较困难的技术,在学习这门技术之前,我们先了解下浏览器内核中的JS引擎与chromium内核的V8引擎相关知识.在浏览器应用中,JS与本地代码互相调用,得益于浏览器内核对 ...
- CEF3开发者系列之进程间消息传递
在使用CEF3作为框架开发过程中,实现WebSockets.XMLHttpRequest.JS与本地客户端交互等功能时,需要在渲染(Render)进程和浏览(Browser)进程中传递消息.CEF3在 ...
随机推荐
- Linux下MySQL的数据文件存放在哪里的??
http://bbs.csdn.net/topics/390620630 mysql> show variables like '%dir%';+------------------------ ...
- vs2017 官方下载地址 和 官方建立脱机安装包的方法
vs2017 官方下载地址: https://docs.microsoft.com/zh-cn/visualstudio/releasenotes/vs2017-relnotes VS2017 官方建 ...
- Android笔记(五十一) 短信验证码集成——mob平台
官方网站:www.mob.com 注册帐号,下载SDK,导入SDK就不说了,主要写一下简单集成如何使用,以后忘记了也可以翻着看看. 详细的可以参考官方文档: http://wiki.mob.com/a ...
- 初识python多线程
目录 GIL锁 Thread类构造方法 Lock类.Rlock类 参考: python3多线程--官方教程中文版 python多线程-1 python多线程-2.1 python多线程-2.2 pyt ...
- Not so Mobile UVA - 839(二叉树的先序遍历)
#include<iostream> using namespace std; int solve(int &W) /*这里一定要用引用,为了赋给它值*/ { int wl, dl ...
- Bicoloring (并查集/二分图)
题目链接 题意: m个查询,每个查询输入a b,表示 顶点a b之间涂色. 规定只能涂颜色0 或者颜色 1,一个节点相连的边 必须涂成相同的颜色. 问 ,输入m组 a b之后,会不会犯规. 思路: 判 ...
- 微信小程序之随笔
先写到这里https://developers.weixin.qq.com/miniprogram/dev/api/open-api/setting/AuthSetting.html
- 学习Kubernetes,这些负载均衡知识点得知道!
负载均衡 负载均衡是高可用架构的一个关键组件,主要用来提高性能和可用性,通过负载均衡将流量分发到多个服务器,同时多服务器能够消除这部分的单点故障. 一个没有使用负载均衡的Web架构一般会长得像这样: ...
- Oracle 中的 TO_DATE 和 TO_CHAR 函数 日期处理
Oracle 中的 TO_DATE 和 TO_CHAR 函数 oracle 中 TO_DATE 函数的时间格式,以 :: 为例 格式 说明 显示值 备注 Year(年): yy two digits( ...
- Linux 之 光标消失隐藏术
下面是 Linux 光标突然不见的解决办法: 直接敲命令行就行 echo -e "\033[?25l" 隐藏光标 echo -e "\033[?25h" 显示 ...