Ở đây (với một số lo lắng) là một bản phác thảo của giải pháp liên kết sử dụng một lần có thể đủ an toàn nếu người ta có thể phụ thuộc vào ip khá ổn định (ít nhất là trong ngắn hạn) cho điện thoại, sử dụng var truy vấn và tạm thời dựa trên $_SERVER['REMOTE_ADDR']
, mặc dù như @Wyck và @GM nói, bất kỳ cửa hậu nào như vậy đều có nguy cơ bảo mật ...
// 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 );
}