web-dev-qa-db-ja.com

クエリ文字列を介してWordPressセッションを別のブラウザに転送することは可能ですか?

ユーザが既存のWordPressセッションを持っていると仮定して、 'wordpress_logged_in_ [hash]'クッキーを受け取り、それをクエリ文字列でエンコードし、そして別のブラウザでセッションを再開することは可能ですか?

私が探求している特定のユースケースは、ユーザーが私のモバイルアプリケーションにログインした場合、彼らが彼らのセッションを失うことなく彼らが現在外部のブラウザでWebviewで見ているWordPressページを開くオプションを与えたいです。

7
Jacob Tabak

これは(多少の不安はあるものの)query varとaを使用して、(少なくとも短期的には)ipが電話に対してかなり一定であることに頼ることができれば十分安全かもしれない使い捨てリンクソリューションのスケッチです。 @Wyckおよび@Gとしてではありますが、$_SERVER['REMOTE_ADDR']に基づく一時的なものです。 M.言う、そのようなバックドアはセキュリティ上のリスクです...

// Make query var & transient name unique to site url and user's IP.
$siteurl = get_site_option( 'siteurl' );
// Could use eg $siteurl = COOKIEHASH; if handier for mobile app.
// Other stuff such as $device_id would be good if available.
define( 'WPSE173878', 'wpse173878' . md5( $siteurl . $_SERVER['REMOTE_ADDR'] ) );

add_action( 'init', function () {
    if ( is_user_logged_in() ) {
        if ( wpse173878_is_set_transient() ) {
            $time = time();
            wpse173878_set_transient( $time );
            // For testing output link in footer.
            add_action( 'wp_footer', function () use ( $time ) {
                // Could just use time() instead as check fudged below in check_transient().
                $link = add_query_arg( WPSE173878, $time, home_url( '/' ) );
                echo '<a href="' . esc_attr( $link ) . '">Copy into a browser</a>';
            } );
        }
        add_action( 'clear_auth_cookie', function() { delete_transient( WPSE173878 ); } );
    } else {
        if ( isset( $_GET[WPSE173878] ) ) {
            wpse173878_check_transient();
        }
    }
} );

// Set transient.
function wpse173878_set_transient( $time ) {
    $user_id = get_current_user_id();
    $remember = wpse173878_remember( $user_id );
    // Will be compromised if ip changes...
    set_transient( WPSE173878, array( $user_id, $time, $remember ), 1 * MINUTE_IN_SECONDS );
}

// Check transient and login.
function wpse173878_check_transient() {
    if ( list( $user_id, $time, $remember ) = get_transient( WPSE173878 ) ) {
        // Fudge time test so that it's estimatable by mobile app.
        if ( $_GET[WPSE173878] + 5 >= $time && $_GET[WPSE173878] - 5 <= $time ) {
            delete_transient( WPSE173878 );
            if ( $user = get_user_by( 'id', $user_id ) ) {
                // Login.
                wp_set_auth_cookie( $user->ID, $remember );
                // Might want to do_action( 'wp_login', $user->user_login, $user );
            }
        }
    }
    // Redirect regardless.
    wp_redirect( remove_query_arg( WPSE173878, wp_unslash( $_SERVER['REQUEST_URI'] ) ) );
    exit;
}

// Whether to set transient.
function wpse173878_is_set_transient() {
    if ( wpse173878_is_in_webview() && ! is_admin() ) {
        // Other conditions such as user pressed button are necessary.
        return true;
    }
    return false;
}

// Are we in a webview?
function wpse173878_is_in_webview() {
    // Pretend Firefox is webview for testing.
    return strpos( $_SERVER['HTTP_USER_AGENT'], 'Firefox' ) !== false;
}

// From "wp-includes/user.php" wp_update_user().
function wpse173878_remember( $user_id ) {
    // Here we calculate the expiration length of the current auth cookie and compare it to the default expiration.
    // If it's greater than this, then we know the user checked 'Remember Me' when they logged in.
    $logged_in_cookie    = wp_parse_auth_cookie( '', 'logged_in' );
    /** This filter is documented in wp-includes/pluggable.php */
    $default_cookie_life = apply_filters( 'auth_cookie_expiration', ( 2 * DAY_IN_SECONDS ), $user_id, false );
    return ( ( $logged_in_cookie['expiration'] - time() ) > $default_cookie_life );
}
4
bonger