我如何访问铬(或任何其他浏览器)cookie

时间:2019-07-18 20:16:19

标签: java cookies browser

我有一个Java应用程序,可将请求发送到google.com,并解析google查询后返回的搜索结果。在Google尚未开始为所有未经授权的用户设置验证码之前,它运行良好。现在我很麻烦,因为要访问搜索结果,用户应该确认验证码。这是我如何解决此问题的想法:

  1. 将JxBrowser添加到我的应用程序中,但这太昂贵了(花费超过一千美元,实现起来很麻烦)

  2. 为google.com硬编码我自己的cookie,但随后我的acc会收到大量请求,我百分百确信,在这种情况下,google会给我每个人的验证码

  3. 最后一个方法(最现实的方法)是要求用户访问Google并完成验证码,然后以某种方式访问​​浏览器cookie

如何使我的应用程序再次运行?有没有人遇到这样的问题。

任何需要帮助的人。谢谢

1 个答案:

答案 0 :(得分:0)

经过一天的搜索和几次尝试,我终于得到了可以访问Chromium和Mozilla cookie的代码。所以这里是:

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.file.Files;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

import com.sun.jna.platform.win32.Crypt32Util;

public class Main {

    public static void main(String[] args) throws IOException {
        ChromeBrowser chrome = new ChromeBrowser();
        //MozillaBrowser mozilla = new MozillaBrowser();
        args=new String[]{"google.com"};
        if(args!=null&&args.length>0) {
            Set<Cookie> cookies = chrome.getCookiesForDomain(args[0]);
            //Set<Cookie> cookies = mozilla.getCookiesForDomain(args[0]);
            for(Cookie cookie : cookies){
                System.out.println(cookie.toString());
            }
        }
    }

    public static abstract class Cookie {

        protected String name;
        protected byte[] encryptedValue;
        protected Date expires;
        protected String path;
        protected String domain;
        protected boolean secure;
        protected boolean httpOnly;
        protected File cookieStore;

        public Cookie(String name, byte[] encryptedValue, Date expires, String path, String domain, boolean secure, boolean httpOnly, File cookieStore) {
            this.name = name;
            this.encryptedValue = encryptedValue;
            this.expires = expires;
            this.path = path;
            this.domain = domain;
            this.secure = secure;
            this.httpOnly = httpOnly;
            this.cookieStore = cookieStore;
        }

        public Cookie(String name, String dencryptedValue, Date expires, String path, String domain, boolean secure, boolean httpOnly, File cookieStore) {
            this.name = name;
            this.expires = expires;
            this.path = path;
            this.domain = domain;
            this.secure = secure;
            this.httpOnly = httpOnly;
            this.cookieStore = cookieStore;
        }

        public String getName() {
            return name;
        }

        public byte[] getEncryptedValue() {
            return encryptedValue;
        }

        public Date getExpires() {
            return expires;
        }

        public String getPath() {
            return path;
        }

        public String getDomain() {
            return domain;
        }

        public boolean isSecure() {
            return secure;
        }

        public boolean isHttpOnly() {
            return httpOnly;
        }

        public File getCookieStore(){
            return cookieStore;
        }

        public abstract boolean isDecrypted();

    }

    public static class DecryptedCookie extends Cookie {

        private String decryptedValue;

        public DecryptedCookie(String name, byte[] encryptedValue, String decryptedValue, Date expires, String path, String domain, boolean secure, boolean httpOnly, File cookieStore) {
            super(name, encryptedValue, expires, path, domain, secure, httpOnly, cookieStore);
            this.decryptedValue = decryptedValue;
        }

        public DecryptedCookie(String name, String decryptedValue, Date expires, String path, String domain, boolean secure, boolean httpOnly, File cookieStore) {
            super(name, decryptedValue, expires, path, domain, secure, httpOnly, cookieStore);
            this.decryptedValue = decryptedValue;
        }

        public String getDecryptedValue(){
            return decryptedValue;
        }

        @Override
        public boolean isDecrypted() {
            return true;
        }

        @Override
        public String toString() {
            return "Cookie [name=" + name + ", value=" + decryptedValue + "]";
        }

    }

    public static class EncryptedCookie extends Cookie {

        public EncryptedCookie(String name, byte[] encryptedValue, Date expires, String path, String domain, boolean secure, boolean httpOnly, File cookieStore) {
            super(name, encryptedValue, expires, path, domain, secure, httpOnly, cookieStore);
        }

        @Override
        public boolean isDecrypted() {
            return false;
        }

        @Override
        public String toString() {
            return "Cookie [name=" + name + " (encrypted)]";
        }

    }

    public static class OS {

        public static String getOsArchitecture() {
            return System.getProperty("os.arch");
        }

        public static String getOperatingSystem() {
            return System.getProperty("os.name");
        }

        public static String getOperatingSystemVersion() {
            return System.getProperty("os.version");
        }

        public static String getIP() throws UnknownHostException {
            InetAddress ip = InetAddress.getLocalHost();
            return ip.getHostAddress();
        }

        public static String getHostname() throws UnknownHostException {
            return InetAddress.getLocalHost().getHostName(); 
        }

        public static boolean isWindows() {
            return (getOperatingSystem().toLowerCase().indexOf("win") >= 0);
        }

        public static boolean isMac() {
            return (getOperatingSystem().toLowerCase().indexOf("mac") >= 0);
        }

        public static boolean isLinux() {
            return (getOperatingSystem().toLowerCase().indexOf("nix") >= 0 || getOperatingSystem().toLowerCase().indexOf("nux") >= 0 || getOperatingSystem().toLowerCase().indexOf("aix") > 0 );
        }

        public static boolean isSolaris() {
            return (getOperatingSystem().toLowerCase().indexOf("sunos") >= 0);
        }

    }

    public static abstract class Browser {

        /**
         * A file that should be used to make a temporary copy of the browser's cookie store
         */
        protected File cookieStoreCopy = new File(".cookies.db");

        /**
         * Returns all cookies
         */
        public Set<Cookie> getCookies() {
            HashSet<Cookie> cookies = new HashSet<Cookie>();
            for(File cookieStore : getCookieStores()){
                cookies.addAll(processCookies(cookieStore, null));
            }
            return cookies;
        }

        /**
         * Returns cookies for a given domain
         */
        public Set<Cookie> getCookiesForDomain(String domain) {
            HashSet<Cookie> cookies = new HashSet<Cookie>();
            for(File cookieStore : getCookieStores()){
                cookies.addAll(processCookies(cookieStore, domain));
            }
            return cookies;
        }

        /**
         * Returns a set of cookie store locations
         * @return
         */
        protected abstract Set<File> getCookieStores();

        /**
         * Processes all cookies in the cookie store for a given domain or all
         * domains if domainFilter is null
         * 
         * @param cookieStore
         * @param domainFilter
         * @return
         */
        protected abstract Set<Cookie> processCookies(File cookieStore, String domainFilter);

        /**
         * Decrypts an encrypted cookie
         * @param encryptedCookie
         * @return
         */
        protected abstract DecryptedCookie decrypt(EncryptedCookie encryptedCookie);

    }

    public static class MozillaBrowser extends Browser {

        protected DecryptedCookie decrypt(EncryptedCookie encryptedCookie){return null;}

        /**
         * Returns a set of cookie store locations
         * @return
         */
        @Override
        protected Set<File> getCookieStores() {
            HashSet<File> cookieStores = new HashSet<File>();

            for(String path:new String[]{"\\Application Data\\Mozilla\\Firefox\\Profiles\\","\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\","/Library/Application Support/Firefox/Profiles/","/.config/Firefox/","/.config/firefox/","/.mozilla/firefox/"}){
                if(new File(System.getProperty("user.home")+path).exists())for(File file:new File(System.getProperty("user.home")+path).listFiles()){
                    if(file.isDirectory()&&file.getName().matches("(?iu)^.*?\\.default$"))cookieStores.add(new File(System.getProperty("user.home")+path+file.getName()+File.separator+"cookies.sqlite"));
                }
            }

            return cookieStores;
        }

        public Set<Cookie> processCookies(File cookieStore,String domainFilter){
            HashSet<Cookie> cookies = new HashSet<Cookie>();
            if(cookieStore.exists()){
                Connection connection=null;
                try {
                    cookieStoreCopy.delete();
                    Files.copy(cookieStore.toPath(),cookieStoreCopy.toPath());
                    Class.forName("org.sqlite.JDBC");
                    connection=DriverManager.getConnection("jdbc:sqlite:"+cookieStoreCopy.getAbsolutePath());
                    Statement statement=connection.createStatement();
                    statement.setQueryTimeout(30);
                    ResultSet result=null;
                    if(domainFilter==null||domainFilter.isEmpty())result=statement.executeQuery("select * from cookies");
                    else result = statement.executeQuery("select * from moz_cookies where HOST like \"%"+domainFilter+"%\"");//ID,BASEDOMAIN,APPID,INBROWSERELEMENT,NAME,VALUE,HOST,PATH,EXPIRY,LASTACCESSED,CREATIONTIME,ISSECURE
                    while(result.next()){
                        String name=result.getString("NAME");
                        String value=result.getString("VALUE");
                        String path=result.getString("PATH");
                        String domain=result.getString("HOST");
                        boolean secure=ChromeBrowser.hasColumn(result,"ISSECURE")?result.getBoolean("ISSECURE"):false;
                        Date expires=result.getDate("EXPIRY");

                        DecryptedCookie decryptedCookie=new DecryptedCookie(name,value,expires,path,domain,secure,false,cookieStore);

                        cookies.add(decryptedCookie);
                        cookieStoreCopy.delete();
                    }
                }
                catch(Exception e){e.printStackTrace();}
                finally{
                    try{
                        if(connection!=null)connection.close();
                    }
                    catch(SQLException e){}
                }
            }
            return cookies;

        }
    }

    /**
     * An implementation of Chrome cookie decryption logic for Mac, Windows, and Linux installs 
     * 
     * References: 
     * 1) http://n8henrie.com/2014/05/decrypt-chrome-cookies-with-python/
     * 2) https://github.com/markushuber/ssnoob
     * 
     * @author Ben Holland
     */
    public static class ChromeBrowser extends Browser {

        private String chromeKeyringPassword = null;

        /**
         * Returns a set of cookie store locations
         * @return
         */
        @Override
        protected Set<File> getCookieStores() {
            HashSet<File> cookieStores = new HashSet<File>();

            // pre Win7
            //cookieStores.add(new File(System.getProperty("user.home") + "\\Application Data\\Google\\Chrome\\User Data\\Default\\Cookies"));

            // Win 7+
            cookieStores.add(new File(System.getProperty("user.home") + "\\AppData\\Local\\Yandex\\YandexBrowser\\User Data\\Default\\Cookies"));
            cookieStores.add(new File(System.getProperty("user.home") + "\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Cookies"));
            //cookieStores.add(new File(System.getProperty("user.home") + "\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\nmx4n1pd.default\\cookies.sqlite"));

            // Mac
            cookieStores.add(new File(System.getProperty("user.home") + "/Library/Application Support/Google/Chrome/Default/Cookies"));

            // Linux
            cookieStores.add(new File(System.getProperty("user.home") + "/.config/chromium/Default/Cookies"));

            return cookieStores;
        }

        public static boolean hasColumn(ResultSet rs, String columnName) throws SQLException {
            ResultSetMetaData rsmd = rs.getMetaData();
            int columns = rsmd.getColumnCount();
            for (int x = 1; x <= columns; x++) {
                if (columnName.equals(rsmd.getColumnName(x))) {
                    return true;
                }
            }
            return false;
        }

        /**
         * Processes all cookies in the cookie store for a given domain or all
         * domains if domainFilter is null
         * 
         * @param cookieStore
         * @param domainFilter
         * @return
         */
        @Override
        protected Set<Cookie> processCookies(File cookieStore, String domainFilter) {
            HashSet<Cookie> cookies = new HashSet<Cookie>();
            if(cookieStore.exists()){
                Connection connection = null;
                try {
                    cookieStoreCopy.delete();
                    Files.copy(cookieStore.toPath(), cookieStoreCopy.toPath());
                    // load the sqlite-JDBC driver using the current class loader
                    Class.forName("org.sqlite.JDBC");
                    // create a database connection
                    connection = DriverManager.getConnection("jdbc:sqlite:" + cookieStoreCopy.getAbsolutePath());
                    Statement statement = connection.createStatement();
                    statement.setQueryTimeout(30); // set timeout to 30 seconds
                    ResultSet result = null;
                    if(domainFilter == null || domainFilter.isEmpty()){
                        result = statement.executeQuery("select * from cookies");
                    } else {
                        result = statement.executeQuery("select * from cookies where host_key like \"%" + domainFilter + "%\"");
                    }
                    while (result.next()) {
                        String name = result.getString("name");
                        byte[] encryptedBytes = result.getBytes("encrypted_value");
                        String path = result.getString("path");
                        String domain = result.getString("host_key");
                        boolean secure = ChromeBrowser.hasColumn(result,"secure")?result.getBoolean("secure"):false;
                        boolean httpOnly = ChromeBrowser.hasColumn(result,"httponly")?result.getBoolean("httponly"):false;
                        Date expires = result.getDate("expires_utc");

                        EncryptedCookie encryptedCookie = new EncryptedCookie(name,
                                                                              encryptedBytes, 
                                                                              expires,
                                                                              path, 
                                                                              domain, 
                                                                              secure,
                                                                              httpOnly, 
                                                                              cookieStore);

                        DecryptedCookie decryptedCookie = decrypt(encryptedCookie);

                        if(decryptedCookie != null){
                            cookies.add(decryptedCookie);
                        } else {
                            cookies.add(encryptedCookie);
                        }
                        cookieStoreCopy.delete();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    // if the error message is "out of memory",
                    // it probably means no database file is found
                } finally {
                    try {
                        if (connection != null){
                            connection.close();
                        }
                    } catch (SQLException e) {
                        // connection close failed
                    }
                }
            }
            return cookies;
        }

        /**
         * Decrypts an encrypted cookie
         * @param encryptedCookie
         * @return
         */
        @Override
        protected DecryptedCookie decrypt(EncryptedCookie encryptedCookie) {
            byte[] decryptedBytes = null;
            if(OS.isWindows()){
                try {
                    System.setProperty("jna.predictable_field_order","true");
                    decryptedBytes = Crypt32Util.cryptUnprotectData(encryptedCookie.getEncryptedValue());
                } catch (Exception e){
                    decryptedBytes = null;
                }
            } else if(OS.isLinux()){
                try {
                    byte[] salt = "saltysalt".getBytes();
                    char[] password = "peanuts".toCharArray();
                    char[] iv = new char[16];
                    Arrays.fill(iv, ' ');
                    int keyLength = 16;

                    int iterations = 1;

                    PBEKeySpec spec = new PBEKeySpec(password, salt, iterations, keyLength * 8);
                    SecretKeyFactory pbkdf2 = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");

                    byte[] aesKey = pbkdf2.generateSecret(spec).getEncoded();

                    SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");

                    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                    cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(new String(iv).getBytes()));

                    // if cookies are encrypted "v10" is a the prefix (has to be removed before decryption)
                    byte[] encryptedBytes = encryptedCookie.getEncryptedValue();
                    if (new String(encryptedCookie.getEncryptedValue()).startsWith("v10")) {
                        encryptedBytes = Arrays.copyOfRange(encryptedBytes, 3, encryptedBytes.length);
                    }
                    decryptedBytes = cipher.doFinal(encryptedBytes);
                } catch (Exception e) {
                    decryptedBytes = null;
                }
            } else if(OS.isMac()){
                // access the decryption password from the keyring manager
                if(chromeKeyringPassword == null){
                    try {
                        chromeKeyringPassword = getMacKeyringPassword("Chrome Safe Storage");
                    } catch (IOException e) {
                        decryptedBytes = null;
                    }
                }
                try {
                    byte[] salt = "saltysalt".getBytes();
                    char[] password = chromeKeyringPassword.toCharArray();
                    char[] iv = new char[16];
                    Arrays.fill(iv, ' ');
                    int keyLength = 16;

                    int iterations = 1003;

                    PBEKeySpec spec = new PBEKeySpec(password, salt, iterations, keyLength * 8);
                    SecretKeyFactory pbkdf2 = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");

                    byte[] aesKey = pbkdf2.generateSecret(spec).getEncoded();

                    SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");

                    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                    cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(new String(iv).getBytes()));

                    // if cookies are encrypted "v10" is a the prefix (has to be removed before decryption)
                    byte[] encryptedBytes = encryptedCookie.getEncryptedValue();
                    if (new String(encryptedCookie.getEncryptedValue()).startsWith("v10")) {
                        encryptedBytes = Arrays.copyOfRange(encryptedBytes, 3, encryptedBytes.length);
                    }
                    decryptedBytes = cipher.doFinal(encryptedBytes);
                } catch (Exception e) {
                    decryptedBytes = null;
                }
            }

            if(decryptedBytes == null){
                return null;
            } else {        
                return new DecryptedCookie(encryptedCookie.getName(),
                                           encryptedCookie.getEncryptedValue(),
                                           new String(decryptedBytes),
                                           encryptedCookie.getExpires(),
                                           encryptedCookie.getPath(),
                                           encryptedCookie.getDomain(),
                                           encryptedCookie.isSecure(),
                                           encryptedCookie.isHttpOnly(),
                                           encryptedCookie.getCookieStore());
            }
        }

        /**
         * Accesses the apple keyring to retrieve the Chrome decryption password
         * @param application
         * @return
         * @throws IOException
         */
        private static String getMacKeyringPassword(String application) throws IOException {
            Runtime rt = Runtime.getRuntime();
            String[] commands = {"security", "find-generic-password","-w", "-s", application};
            Process proc = rt.exec(commands);
            BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            String result = "";
            String s = null;
            while ((s = stdInput.readLine()) != null) {
                result += s;
            }
            return result;
        }

    }

}