单点登录流程简介
我们都知道BS架构会在浏览器Cookie中存放一些信息,比如登录状态。浏览器在发起请求的时候会按照域名(Domain)将这个域名下所有的cookie放到Http请求的Header中。
服务端在收到Http请求之后会获取从Cookie中拿到所需的信息。
拿单点登录举例子,A系统、B系统、CAS单点登录系统
下面是CAS登录系统的一个大致的流程,好久没看这块了可能和实际的有些出入。
不过大致都是通过cookie放登录信息的。
为什么要拿浏览器本地的cookie
爱折腾,想着开发一些小工具将频繁的操作通过脚本简单化。 如:我们开发中经常会登录服务器看日志,打开网页->搜索集群名字->找到ip->复制ip到ssh登录,那么能不能讲这个操作合成一步完成。 其中打开网页搜索集群,这个操作就需要用到登录状态访问。 要拿到这个登录状态最标准的是接公司的单点登录系统。。。但是这样太麻烦了。 于是就想,浏览器本地有cookie直接拿行不行,这肯定能行。现在开发生态非常丰富基本你能想到的功能都能在网上找到。 下面是Python提取浏览器cookie的类库
pip install browsercookie
import browsercookie
import json
chrome = browsercookie.chrome()
cookie_list = []
for cookie in chrome:
cookie_list.append({
"domain": cookie.domain,
"name": cookie.name,
"value": cookie.value,
"expires": cookie.expires,
"path": cookie.path
})
print(json.dumps(cookie_list))
这几行代码能将chrome的cookie打印到控制台。 以前开发的Alfred工作流大部分使用Python2.7开发的,所以这个类库能直接用。 拿到cookie之后后面的流程大部分就能通过解析Http response拿到。
Java获取本地Cookie
通过Java从http request中拿Cookie很简单,但是我要拿本地的Cookie有没有开源的工具呢?
在网上找了很久,但是只有Windows系统的解析方式。。。Mac的cookie加密方式和win不一样,并且没有现成的。
自己尝试使用Java解密cookie,并没有成功。
曲线救国,用Java调用Python拿到cookie就行了。于是我将 Python browsercookie 类库的代码复制到了Java代码中用 StringBuilder拼接起来,
然后用的时候讲这部分当做字符串写到本地文件中,然后通过Java执行Python拿到cookie。
执行以下的代码本地需要有python2.7不支持python3
调用Python的java代码如下,依赖 apache-commons-io apache-commons-exec
public static List<CookieDTO> extractChromeCookies() throws IOException {
DefaultExecutor executor = new DefaultExecutor();
executor.setExitValues(null);
ExecuteWatchdog watchdog = new ExecuteWatchdog(60000);
executor.setWatchdog(watchdog);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ByteArrayOutputStream errorStream = new ByteArrayOutputStream();
PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream, errorStream);
executor.setStreamHandler(streamHandler);
String pythonScriptFilePath = Joiner.on(File.separator)
.join(getWorkspace(), "cookies", "extract_cookies.py");
// python 命令写入py文件,文件加运行权限
File pyFile = new File(pythonScriptFilePath);
//noinspection ResultOfMethodCallIgnored
pyFile.getParentFile().mkdirs();
FileUtils.write(pyFile, getPythonCommand(), StandardCharsets.UTF_8);
new DefaultExecutor().execute(CommandLine.parse("chmod 777 " + pythonScriptFilePath), System.getenv());
// 构建执行的命令
CommandLine pythonCommand = CommandLine.parse("/usr/bin/env python");
pythonCommand.addArgument(pythonScriptFilePath);
log.info("【执行extract_cookies.py】" + pythonCommand);
executor.execute(pythonCommand, System.getenv());
String cookieListJson = outputStream.toString(StandardCharsets.UTF_8);
if (StringUtils.isNotBlank(cookieListJson)) {
log.info("【执行python返回】" + cookieListJson);
}
String errorMsg = errorStream.toString(StandardCharsets.UTF_8);
if (StringUtils.isNotBlank(errorMsg)) {
log.info("【执行python返回Error】" + errorMsg);
}
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
return gson.fromJson(cookieListJson, new TypeToken<ArrayList<CookieDTO>>() {
}.getType());
}
@Data
public static class CookieDTO {
private String domain;
private String name;
private String value;
private String expires;
private String path;
}
下面是python代码的字符串拼接方法
private static String getPythonCommand() {
//noinspection StringBufferReplaceableByString
StringBuilder builder = new StringBuilder(1024 * 1024 * 18);
builder.append("# -*- coding: utf-8 -*-\n");
builder.append("import os\n");
builder.append("import sys\n");
builder.append("import time\n");
builder.append("import glob\n");
builder.append("try:\n");
builder.append(" import cookielib\n");
builder.append("except ImportError:\n");
builder.append(" import http.cookiejar as cookielib\n");
builder.append("from contextlib import contextmanager\n");
builder.append("import tempfile\n");
builder.append("try:\n");
builder.append(" import json\n");
builder.append("except ImportError:\n");
builder.append(" import simplejson as json\n");
builder.append("try:\n");
builder.append(" import ConfigParser as configparser\n");
builder.append("except ImportError:\n");
builder.append(" import configparser\n");
builder.append("try:\n");
builder.append(" # should use Cryptodome in windows instead of Crypto\n");
builder.append(" # otherwise will raise an import error\n");
builder.append(" from Cryptodome.Protocol.KDF import PBKDF2\n");
builder.append(" from Cryptodome.Cipher import AES\n");
builder.append("except ImportError:\n");
builder.append(" from Crypto.Protocol.KDF import PBKDF2\n");
builder.append(" from Crypto.Cipher import AES\n");
builder.append("\n");
builder.append("try:\n");
builder.append(" from pysqlite2 import dbapi2 as sqlite3\n");
builder.append("except ImportError:\n");
builder.append(" import sqlite3\n");
builder.append("\n");
builder.append("if sys.platform == 'darwin': # darwin is OSX\n");
builder.append(" from struct import unpack\n");
builder.append(" try:\n");
builder.append(" from StringIO import StringIO # only works for python2\n");
builder.append(" except ImportError:\n");
builder.append(" from io import BytesIO as StringIO # only works for python3\n");
builder.append("\n");
builder.append("import lz4.block\n");
builder.append("import keyring\n");
builder.append("\n");
builder.append("class BrowserCookieError(Exception):\n");
builder.append(" pass\n");
builder.append("\n");
builder.append("\n");
builder.append("@contextmanager\n");
builder.append("def create_local_copy(cookie_file):\n");
builder.append(" # check if cookie file exists\n");
builder.append(" if os.path.exists(cookie_file):\n");
builder.append(" # copy to random name in tmp folder\n");
builder.append(" tmp_cookie_file = tempfile.NamedTemporaryFile(suffix='.sqlite').name\n");
builder.append(" open(tmp_cookie_file, 'wb').write(open(cookie_file, 'rb').read())\n");
builder.append(" yield tmp_cookie_file\n");
builder.append(" else:\n");
builder.append(" raise BrowserCookieError('Can not find cookie file at: ' + cookie_file)\n");
builder.append("\n");
builder.append(" os.remove(tmp_cookie_file)\n");
builder.append("\n");
builder.append("\n");
builder.append("class BrowserCookieLoader(object):\n");
builder.append(" def __init__(self, cookie_files=None):\n");
builder.append(" cookie_files = cookie_files or self.find_cookie_files()\n");
builder.append(" self.cookie_files = list(cookie_files)\n");
builder.append("\n");
builder.append(" def find_cookie_files(self):\n");
builder.append(" '''Return a list of cookie file locations valid for this loader'''\n");
builder.append(" raise NotImplementedError\n");
builder.append("\n");
builder.append(" def get_cookies(self):\n");
builder.append(" '''Return all cookies (May include duplicates from different sources)'''\n");
builder.append(" raise NotImplementedError\n");
builder.append("\n");
builder.append(" def load(self):\n");
builder.append(" '''Load cookies into a cookiejar'''\n");
builder.append(" cookie_jar = cookielib.CookieJar()\n");
builder.append(" for cookie in self.get_cookies():\n");
builder.append(" cookie_jar.set_cookie(cookie)\n");
builder.append(" return cookie_jar\n");
builder.append("\n");
builder.append("\n");
builder.append("class Chrome(BrowserCookieLoader):\n");
builder.append(" def __str__(self):\n");
builder.append(" return 'chrome'\n");
builder.append("\n");
builder.append(" def find_cookie_files(self):\n");
builder.append(" for pattern in [\n");
builder.append(" os.path.expanduser('~/Library/Application Support/Google/Chrome/Default/Cookies'),\n");
builder.append(" os.path.expanduser('~/Library/Application Support/Google/Chrome/Profile */Cookies'),\n");
builder.append(" os.path.expanduser('~/Library/Application Support/Vivaldi/Default/Cookies'),\n");
builder.append(" os.path.expanduser('~/Library/Application Support/Vivaldi/Profile */Cookies'),\n");
builder.append(" os.path.expanduser('~/.config/chromium/Default/Cookies'),\n");
builder.append(" os.path.expanduser('~/.config/chromium/Profile */Cookies'),\n");
builder.append(" os.path.expanduser('~/.config/google-chrome/Default/Cookies'),\n");
builder.append(" os.path.expanduser('~/.config/google-chrome/Profile */Cookies'),\n");
builder.append(" os.path.expanduser('~/.config/vivaldi/Default/Cookies'),\n");
builder.append(" os.path.expanduser('~/.config/vivaldi/Profile */Cookies'),\n");
builder.append(" os.path.join(os.getenv('APPDATA', ''), r'..\\Local\\Google\\Chrome\\User Data\\Default\\Cookies'),\n");
builder.append(" os.path.join(os.getenv('APPDATA', ''), r'..\\Local\\Google\\Chrome\\User Data\\Profile *\\Cookies'),\n");
builder.append(" os.path.join(os.getenv('APPDATA', ''), r'..\\Local\\Vivaldi\\User Data\\Default\\Cookies'),\n");
builder.append(" os.path.join(os.getenv('APPDATA', ''), r'..\\Local\\Vivaldi\\User Data\\Profile *\\Cookies'),\n");
builder.append(" ]:\n");
builder.append(" for result in glob.glob(pattern):\n");
builder.append(" yield result\n");
builder.append("\n");
builder.append(" def get_cookies(self):\n");
builder.append(" salt = b'saltysalt'\n");
builder.append(" length = 16\n");
builder.append(" if sys.platform == 'darwin':\n");
builder.append(" # running Chrome on OSX\n");
builder.append(" my_pass = keyring.get_password('Chrome Safe Storage', 'Chrome')\n");
builder.append(" my_pass = my_pass.encode('utf8')\n");
builder.append(" iterations = 1003\n");
builder.append(" key = PBKDF2(my_pass, salt, length, iterations)\n");
builder.append("\n");
builder.append(" elif sys.platform.startswith('linux'):\n");
builder.append(" # running Chrome on Linux\n");
builder.append(" my_pass = 'peanuts'.encode('utf8')\n");
builder.append(" iterations = 1\n");
builder.append(" key = PBKDF2(my_pass, salt, length, iterations)\n");
builder.append("\n");
builder.append(" elif sys.platform == 'win32':\n");
builder.append(" key = None\n");
builder.append(" else:\n");
builder.append(" raise BrowserCookieError('Unsupported operating system: ' + sys.platform)\n");
builder.append("\n");
builder.append(" for cookie_file in self.cookie_files:\n");
builder.append(" with create_local_copy(cookie_file) as tmp_cookie_file:\n");
builder.append(" con = sqlite3.connect(tmp_cookie_file)\n");
builder.append(" cur = con.cursor()\n");
builder.append(" cur.execute('SELECT value FROM meta WHERE key = \"version\";')\n");
builder.append(" version = int(cur.fetchone()[0])\n");
builder.append(" query = 'SELECT host_key, path, is_secure, expires_utc, name, value, encrypted_value FROM cookies;'\n");
builder.append(" if version < 10:\n");
builder.append(" query = query.replace('is_', '')\n");
builder.append(" cur.execute(query)\n");
builder.append(" for item in cur.fetchall():\n");
builder.append(" host, path, secure, expires, name = item[:5]\n");
builder.append(" value = self._decrypt(item[5], item[6], key=key)\n");
builder.append(" yield create_cookie(host, path, secure, expires, name, value)\n");
builder.append(" con.close()\n");
builder.append("\n");
builder.append(" def _decrypt(self, value, encrypted_value, key):\n");
builder.append(" if (sys.platform == 'darwin') or sys.platform.startswith('linux'):\n");
builder.append(" if value or (encrypted_value[:3] != b'v10'):\n");
builder.append(" return value\n");
builder.append("\n");
builder.append(" # Encrypted cookies should be prefixed with 'v10' according to the\n");
builder.append(" # Chromium code. Strip it off.\n");
builder.append(" encrypted_value = encrypted_value[3:]\n");
builder.append("\n");
builder.append(" def clean(x):\n");
builder.append(" last = x[-1]\n");
builder.append(" if isinstance(last, int):\n");
builder.append(" return x[:-last].decode('utf8')\n");
builder.append(" else:\n");
builder.append(" return x[:-ord(last)].decode('utf8')\n");
builder.append("\n");
builder.append(" iv = b' ' * 16\n");
builder.append(" cipher = AES.new(key, AES.MODE_CBC, IV=iv)\n");
builder.append(" decrypted = cipher.decrypt(encrypted_value)\n");
builder.append(" return clean(decrypted)\n");
builder.append(" else:\n");
builder.append(" # Must be win32 (on win32, all chrome cookies are encrypted)\n");
builder.append(" try:\n");
builder.append(" import win32crypt\n");
builder.append(" except ImportError:\n");
builder.append(" raise BrowserCookieError('win32crypt must be available to decrypt Chrome cookie on Windows')\n");
builder.append(" return win32crypt.CryptUnprotectData(encrypted_value, None, None, None, 0)[1].decode('utf-8')\n");
builder.append("\n");
builder.append("\n");
builder.append("class Firefox(BrowserCookieLoader):\n");
builder.append(" def __str__(self):\n");
builder.append(" return 'firefox'\n");
builder.append("\n");
builder.append(" def parse_profile(self, profile):\n");
builder.append(" cp = configparser.ConfigParser()\n");
builder.append(" cp.read(profile)\n");
builder.append(" path = None\n");
builder.append(" for section in cp.sections():\n");
builder.append(" try:\n");
builder.append(" if cp.getboolean(section, 'IsRelative'):\n");
builder.append(" path = os.path.dirname(profile) + '/' + cp.get(section, 'Path')\n");
builder.append(" else:\n");
builder.append(" path = cp.get(section, 'Path')\n");
builder.append(" if cp.has_option(section, 'Default'):\n");
builder.append(" return os.path.abspath(os.path.expanduser(path))\n");
builder.append(" except configparser.NoOptionError:\n");
builder.append(" pass\n");
builder.append(" if path:\n");
builder.append(" return os.path.abspath(os.path.expanduser(path))\n");
builder.append(" raise BrowserCookieError('No default Firefox profile found')\n");
builder.append("\n");
builder.append(" def find_default_profile(self):\n");
builder.append(" if sys.platform == 'darwin':\n");
builder.append(" return glob.glob(os.path.expanduser('~/Library/Application Support/Firefox/profiles.ini'))\n");
builder.append(" elif sys.platform.startswith('linux'):\n");
builder.append(" return glob.glob(os.path.expanduser('~/.mozilla/firefox/profiles.ini'))\n");
builder.append(" elif sys.platform == 'win32':\n");
builder.append(" return glob.glob(os.path.join(os.getenv('APPDATA', ''), 'Mozilla/Firefox/profiles.ini'))\n");
builder.append(" else:\n");
builder.append(" raise BrowserCookieError('Unsupported operating system: ' + sys.platform)\n");
builder.append("\n");
builder.append(" def find_cookie_files(self):\n");
builder.append(" profile = self.find_default_profile()\n");
builder.append(" if not profile:\n");
builder.append(" raise BrowserCookieError('Could not find default Firefox profile')\n");
builder.append(" path = self.parse_profile(profile[0])\n");
builder.append(" if not path:\n");
builder.append(" raise BrowserCookieError('Could not find path to default Firefox profile')\n");
builder.append(" cookie_files = glob.glob(os.path.expanduser(path + '/cookies.sqlite'))\n");
builder.append(" if cookie_files:\n");
builder.append(" return cookie_files\n");
builder.append(" else:\n");
builder.append(" raise BrowserCookieError('Failed to find Firefox cookies')\n");
builder.append("\n");
builder.append(" def get_cookies(self):\n");
builder.append(" for cookie_file in self.cookie_files:\n");
builder.append(" with create_local_copy(cookie_file) as tmp_cookie_file:\n");
builder.append(" con = sqlite3.connect(tmp_cookie_file)\n");
builder.append(" cur = con.cursor()\n");
builder.append(" cur.execute('select host, path, isSecure, expiry, name, value from moz_cookies')\n");
builder.append("\n");
builder.append(" for item in cur.fetchall():\n");
builder.append(" yield create_cookie(*item)\n");
builder.append(" con.close()\n");
builder.append("\n");
builder.append(" # current sessions are saved in sessionstore.js/recovery.json/recovery.jsonlz4\n");
builder.append(" session_files = (os.path.join(os.path.dirname(cookie_file), 'sessionstore.js'),\n");
builder.append(" os.path.join(os.path.dirname(cookie_file), 'sessionstore-backups', 'recovery.js'),\n");
builder.append(" os.path.join(os.path.dirname(cookie_file), 'sessionstore-backups', 'recovery.json'),\n");
builder.append(" os.path.join(os.path.dirname(cookie_file), 'sessionstore-backups', 'recovery.jsonlz4'))\n");
builder.append(" for file_path in session_files:\n");
builder.append(" if os.path.exists(file_path):\n");
builder.append(" if file_path.endswith('4'):\n");
builder.append(" try:\n");
builder.append(" session_file = open(file_path, 'rb')\n");
builder.append(" # skip the first 8 bytes to avoid decompress failure (custom Mozilla header)\n");
builder.append(" session_file.seek(8)\n");
builder.append(" json_data = json.loads(lz4.block.decompress(session_file.read()).decode())\n");
builder.append(" except IOError as e:\n");
builder.append(" print('Could not read file:', str(e))\n");
builder.append(" except ValueError as e:\n");
builder.append(" print('Error parsing Firefox session file:', str(e))\n");
builder.append(" else:\n");
builder.append(" try:\n");
builder.append(" json_data = json.loads(open(file_path, 'rb').read().decode('utf-8'))\n");
builder.append(" except IOError as e:\n");
builder.append(" print('Could not read file:', str(e))\n");
builder.append(" except ValueError as e:\n");
builder.append(" print('Error parsing firefox session JSON:', str(e))\n");
builder.append("\n");
builder.append(" if 'json_data' in locals():\n");
builder.append(" expires = str(int(time.time()) + 3600 * 24 * 7)\n");
builder.append(" for window in json_data.get('windows', []):\n");
builder.append(" for cookie in window.get('cookies', []):\n");
builder.append(" yield create_cookie(cookie.get('host', ''), cookie.get('path', ''), False, expires, cookie.get('name', ''), cookie.get('value', ''))\n");
builder.append(" else:\n");
builder.append(" print('Could not find any Firefox session files')\n");
builder.append("\n");
builder.append("class Safari(BrowserCookieLoader):\n");
builder.append(" def __str__(self):\n");
builder.append(" return 'safari'\n");
builder.append("\n");
builder.append(" def find_cookie_files(self):\n");
builder.append(" if (sys.platform != 'darwin'): # checks if using OSX\n");
builder.append(" BrowserCookieError('Safari is only available on OSX')\n");
builder.append(" else:\n");
builder.append(" cookie_files = glob.glob(os.path.expanduser('~/Library/Cookies'))\n");
builder.append(" if cookie_files:\n");
builder.append(" return cookie_files\n");
builder.append(" else:\n");
builder.append(" raise BrowserCookieError('Failed to find Safari cookies')\n");
builder.append("\n");
builder.append(" def get_cookies(self):\n");
builder.append(" FilePath = os.path.expanduser('~/Library/Cookies/Cookies.binarycookies')\n");
builder.append("\n");
builder.append(" try:\n");
builder.append(" binary_file = open(FilePath, 'rb')\n");
builder.append(" except IOError:\n");
builder.append(" BrowserCookieError('File Not Found :' + FilePath)\n");
builder.append(" exit()\n");
builder.append("\n");
builder.append(" binary_file.read(4)# will equal 'cook', which stands for cookies\n");
builder.append("\n");
builder.append(" num_pages = unpack('>i', binary_file.read(4))[0]\n");
builder.append("\n");
builder.append(" page_sizes = []\n");
builder.append(" for _ in range(num_pages):\n");
builder.append(" page_sizes.append(unpack('>i', binary_file.read(4))[0])\n");
builder.append("\n");
builder.append(" pages = []\n");
builder.append(" for ps in page_sizes:\n");
builder.append(" pages.append(binary_file.read(ps))\n");
builder.append("\n");
builder.append(" for page in pages:\n");
builder.append(" page = StringIO(page)\n");
builder.append(" page.read(4)\n");
builder.append(" num_cookies = unpack('<i', page.read(4))[0]\n");
builder.append("\n");
builder.append(" cookie_offsets = []\n");
builder.append(" for _ in range(num_cookies):\n");
builder.append(" cookie_offsets.append(unpack('<i', page.read(4))[0])\n");
builder.append("\n");
builder.append(" page.read(4)\n");
builder.append("\n");
builder.append(" cookie = ''\n");
builder.append(" for offset in cookie_offsets:\n");
builder.append(" page.seek(offset)\n");
builder.append(" cookiesize = unpack('<i', page.read(4))[0]\n");
builder.append(" cookie = StringIO(page.read(cookiesize))\n");
builder.append("\n");
builder.append(" cookie.read(4)\n");
builder.append("\n");
builder.append(" flags = unpack('<i', cookie.read(4))[0]\n");
builder.append(" cookie_flags = ''\n");
builder.append(" if flags == 0:\n");
builder.append(" cookie_flags = False # if nothing at all\n");
builder.append(" if flags == 1:\n");
builder.append(" cookie_flags = True # if Secure\n");
builder.append(" elif flags == 4:\n");
builder.append(" cookie_flags = False # if Http only\n");
builder.append(" elif flags == 5:\n");
builder.append(" cookie_flags = True # if Secure and Http only\n");
builder.append(" else:\n");
builder.append(" cookie_flags = False # if Unknown\n");
builder.append("\n");
builder.append(" cookie.read(4)\n");
builder.append("\n");
builder.append(" urloffset = unpack('<i', cookie.read(4))[0]\n");
builder.append(" nameoffset = unpack('<i', cookie.read(4))[0]\n");
builder.append(" pathoffset = unpack('<i', cookie.read(4))[0]\n");
builder.append(" valueoffset = unpack('<i', cookie.read(4))[0]\n");
builder.append("\n");
builder.append(" expiry_date = str(int(unpack('<d', cookie.read(8))[0] + 978307200))\n");
builder.append("\n");
builder.append(" # create_date = str(int(unpack('<d', cookie.read(8))[0] + 978307200)) no need of it here...\n");
builder.append("\n");
builder.append(" # endofcookie = cookie.read(8) no need it either...\n");
builder.append("\n");
builder.append(" cookie.seek(urloffset - 4)\n");
builder.append(" host = ''\n");
builder.append(" u = cookie.read(1)\n");
builder.append(" while unpack('<b', u)[0] != 0:\n");
builder.append(" host = host + u.decode('utf-8') # in bytes have to be decoded\n");
builder.append(" u = cookie.read(1)\n");
builder.append("\n");
builder.append(" cookie.seek(nameoffset - 4)\n");
builder.append(" name = ''\n");
builder.append(" n = cookie.read(1)\n");
builder.append(" while unpack('<b', n)[0] != 0:\n");
builder.append(" name = name + n.decode('utf-8')\n");
builder.append(" n = cookie.read(1)\n");
builder.append("\n");
builder.append(" cookie.seek(pathoffset - 4)\n");
builder.append(" path = ''\n");
builder.append(" pa = cookie.read(1)\n");
builder.append(" while unpack('<b', pa)[0] != 0:\n");
builder.append(" path = path + pa.decode('utf-8')\n");
builder.append(" pa = cookie.read(1)\n");
builder.append("\n");
builder.append(" cookie.seek(valueoffset - 4)\n");
builder.append(" value = ''\n");
builder.append(" va = cookie.read(1)\n");
builder.append(" while unpack('<b', va)[0] != 0:\n");
builder.append(" value = value + va.decode('utf-8')\n");
builder.append(" va = cookie.read(1)\n");
builder.append("\n");
builder.append(" yield create_cookie(host, path, cookie_flags, expiry_date, name, value)\n");
builder.append("\n");
builder.append(" binary_file.close()\n");
builder.append("\n");
builder.append("\n");
builder.append("\n");
builder.append("def create_cookie(host, path, secure, expires, name, value):\n");
builder.append(" return cookielib.Cookie(0, name, value, None, False, host, host.startswith('.'), host.startswith('.'), path, True, secure, expires, False, None, None, {})\n");
builder.append("\n");
builder.append("def chrome(cookie_file=None):\n");
builder.append(" return Chrome(cookie_file).load()\n");
builder.append("\n");
builder.append("def firefox(cookie_file=None):\n");
builder.append(" return Firefox(cookie_file).load()\n");
builder.append("\n");
builder.append("def safari(cookie_file=None):\n");
builder.append(" return Safari(cookie_file).load()\n");
builder.append("\n");
builder.append("def _get_cookies():\n");
builder.append(" '''Return all cookies from all browsers'''\n");
builder.append(" for klass in [Chrome, Firefox]:\n");
builder.append(" try:\n");
builder.append(" for cookie in klass().get_cookies():\n");
builder.append(" yield cookie\n");
builder.append(" except BrowserCookieError:\n");
builder.append(" pass\n");
builder.append("\n");
builder.append("def load():\n");
builder.append(" cookie_jar = cookielib.CookieJar()\n");
builder.append("\n");
builder.append(" for cookie in sorted(_get_cookies(), key=lambda cookie: cookie.expires):\n");
builder.append(" cookie_jar.set_cookie(cookie)\n");
builder.append("\n");
builder.append(" return cookie_jar\n");
builder.append("\n");
builder.append("\n");
builder.append("\n");
builder.append("# ------------------------------------------------------------------------------\n");
builder.append("\n");
builder.append("file_path = os.path.expanduser('~') + os.sep + 'Desktop' + os.sep + 'cookies.txt'\n");
builder.append("if sys.argv and sys.argv.__len__() > 1:\n");
builder.append(" file_path = sys.argv[1]\n");
builder.append("\n");
builder.append("chrome = chrome()\n");
builder.append("cookie_list = []\n");
builder.append("for cookie in chrome:\n");
builder.append(" cookie_list.append({\n");
builder.append(" 'domain': cookie.domain,\n");
builder.append(" 'name': cookie.name,\n");
builder.append(" 'value': cookie.value,\n");
builder.append(" 'expires': cookie.expires,\n");
builder.append(" 'path': cookie.path\n");
builder.append(" })\n");
builder.append("\n");
builder.append("print json.dumps(cookie_list)\n");
return builder.toString();
}