Android Webview,formhash无法在某些Android设备上运行

时间:2014-02-19 17:50:00

标签: javascript android html hash webview

我一直在Android和iOS上开发Web应用程序并使用Web视图。一切都在iPhone上工作正常,但在Android上它并不适用于所有设备,它让我发疯。在五个Android设备上它运行良好,但在两个设备上它不会比登录页面更进一步。但它确实可以在浏览器中的移动网站(而不是应用程序)上运行。

移动应用程序未运行的设备是HTC One(v4.3)和Acer Liquid Z3(v4.2)。另一个设备也是HTC One(v4.3)它可以工作,这使得这个问题很难理解和解决。

打开应用程序时的第一个窗口是一个简单的登录窗口。在它不工作的设备上,它只是重新加载页面,用户可以再次登录。使用数据库中的详细信息检查登录信息。当它工作(或在浏览器中打开)时,它会加载到新页面。

MainActivity.java:

public class MainActivity extends Activity {

WebView mWebView;
private ProgressBar loadingProgressBar;

@SuppressLint("SetJavaScriptEnabled")
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);

    setContentView(R.layout.activity_main);

    mWebView = (WebView) findViewById(R.id.webview);

    mWebView.getSettings().setJavaScriptEnabled(true);
    mWebView.setWebViewClient(new DivumWebViewClient());

    mWebView.loadUrl("http://www.xxxx.com/index.php");

    loadingProgressBar = (ProgressBar) findViewById(R.id.progressbar_title);
    mWebView.setWebChromeClient(new WebChromeClient() {
        @Override
        public void onProgressChanged(WebView view, int newProgress) {
            super.onProgressChanged(view, newProgress);
            loadingProgressBar.setProgress(newProgress);
            if (newProgress == 100) {
                loadingProgressBar.setVisibility(View.GONE);
            } else {
                loadingProgressBar.setVisibility(View.VISIBLE);
            }
        }
    });

}

private class DivumWebViewClient extends WebViewClient {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        view.loadUrl(url);
        return true;
    }
}
}

的index.php

.....
<body class="blue-bg">
<?php
if (isset($_GET['error'])) {
    echo '<p class="error">Error Logging In!</p>';
} 
sec_session_start(); 
if (isset($_POST['email'], $_POST['p'])) {
    $email = $_POST['email'];
    $password = $_POST['p']; 

    if (login($email, $password, $mysqli) == true) {
        // Login success 
        header('Location: dashboard.php');
        exit;
    } else if(login($email, $password, $mysqli) == false){
        $error['error'] = "<p>Enter login details:</p>\n";
    }
} 
?>  
<div class="signin" style="margin-top: 0;">

    <div class="signin-body">

        <a href="index.php" title="Login" class="pull-right">
            <img src="../assets/images/logo.jpg" title="Login" alt="Login">
        </a>
        <br><h3>Login</h3>
        <?=$error['error']?>
        <form action="<?=$_SERVER['PHP_SELF']?>" id="login-validatie" method="post"        name="login_form">                  
            <div class="form-group">
             <input type="text" class="form-control" placeholder="Emailadres" name="email" id="email">
            </div>

            <div class="form-group">
             <input type="password" class="form-control" placeholder="Wachtwoord" name="password" id="password">
            </div>


            <div class="form-group clearfix">
            <input type="submit" onclick="formhash(this.form, this.form.password);" class="btn btn-med blue-bg pull-right" value="Inloggen">
            </div>

            <hr>          
        </form>

    </div>

</div>
<script src="../assets/js/scripts.js"></script>    
</body>
</html>

我不知道它是不是一个bug或什么的。奇怪的是它适用于大多数设备,但不适用于某些设备。它也适用于浏览器,这让我觉得它与Android中的Web视图有关。我处于死路,并感谢每一个帮助。谢谢!

更新 我终于找到了问题所在,它与表格散列有关。密码在webview中的某些Android设备上提供了不同的sha512哈希,这使得无法登录。不知道在某些设备上它是否是Android网页视图的限制,有谁知道如何解决这个问题?

forms.js

function formhash(form, password) {
    // Create a new element input, this will be our hashed password field. 
    var p = document.createElement("input");

    // Add the new element to our form. 
    p.name = "p";
    p.type = "hidden";
    p.value = hex_sha512(password.value);

    form.appendChild(p);

    // Make sure the plaintext password doesn't get sent. 
    password.value = "";

    // Finally submit the form. 
    form.submit();
}

的functions.php

function login($email, $password, $mysqli) {
    // Using prepared statements means that SQL injection is not possible. 
    if ($stmt = $mysqli->prepare("SELECT id, username, password, salt FROM x WHERE email = ? LIMIT 1")) {
        $stmt->bind_param('s', $email);  // Bind "$email" to parameter.
        $stmt->execute();    // Execute the prepared query.
        $stmt->store_result();

        // get variables from result.
        $stmt->bind_result($user_id, $username, $db_password, $salt);
        $stmt->fetch();

        // hash the password with the unique salt.
        $password = hash('sha512', $password . $salt);
        ?><script> var x; x = "<?php print($password); ?>"; console.log("Logging: password is " + x); </script><?

        if ($stmt->num_rows == 1) {
            // If the user exists we check if the account is locked
            // from too many login attempts 

            if (checkbrute($user_id, $mysqli) == true) {
                // Account is locked 
                // Send an email to user saying their account is locked
                return false;
            } else {
                // Check if the password in the database matches
                // the password the user submitted.
                if ($db_password == $password) {
                    // Password is correct!
                    // Get the user-agent string of the user.
                    $user_browser = $_SERVER['HTTP_USER_AGENT'];
                    // XSS protection as we might print this value
                    $user_id = preg_replace("/[^0-9]+/", "", $user_id);
                    $_SESSION['user_id'] = $user_id;
                    // XSS protection as we might print this value
                    $username = preg_replace("/[^a-zA-Z0-9_\-]+/", 
                                                            "", 
                                                            $username);
                    $_SESSION['username'] = $username;
                    $_SESSION['login_string'] = hash('sha512', 
                          $password . $user_browser);
                    // Login successful.
                    return true;
                } else {
                    // Password is not correct
                    // We record this attempt in the database
                    $now = time();
                    $mysqli->query("INSERT INTO login_attempts(user_id, time)
                                VALUES ('$user_id', '$now')");
                    return false;
                }
            }
        } else {
            // No user exists.
            return false;
        }
    }
}

在iPhone应用程序,Androids浏览器,桌面浏览器或某些Android应用程序上使用时,它会提供一个sha5哈希:c7d9a2def4f8d0f9c4b65d7522566ed33549b266174b2b12ae7f7b047e7efed2e92d18e552d1c812f073e794d16feb8ccf9df85399c475f24571472dece2d9b2

但是在某些Android设备上,当出于某种奇怪的原因使用相同的密码时,它会给出两个哈希值中的一个: 98488504186f9f69041c80217c311cfb4772f46319c945d3bc30c0c2db5650e675774bc6978749770b598e70d4553ec0391e7d3ec0b56d51eef51eeadbb7e10e

a3e08c365ef82d4256d8e58fd63b53d63d50b6b3cac3cdaba395cc73289e5f955491f11f06408c2c6e6ae531d69ddb10f234ecef0cf375d9782abea27909c9ef

2 个答案:

答案 0 :(得分:1)

我之前也遇到过这个问题,我的webview无法在当前窗口中打开一个url,经过一段时间后,android os会拿起url并尝试在浏览器中打开它。我有一个非常类似的实现。

直接来自documentation正是您所寻找的我相信:

Creating and setting a WebViewClient subclass. It will be called when things happen that impact the rendering of the content, eg, errors or form submissions. You can also intercept URL loading here (via shouldOverrideUrlLoading()).

shouldOverrideUrlLoading()方法告诉webview我想在通过此WebView提交的所有网址上处理加载操作

你可以看看我是如何处理My Github Project从第226行开始的,其中我添加了一个扩展WebViewClient类的额外内部类。

附注

这适用于我支持的大多数设备上的应用程序。但您可能还想确保您的URL完全合格。我发现当我使用的任何网址没有

http://

在它前面的

,即使使用Additional WebViewClient,WebView也无法加载URL。 Object和shouldOverrideUrlLoading()调用。

加载失败后您是否尝试过以下操作?看看这是否会刷新webview的状态,一旦它出现,就向你真正想要的URL发出一个新的请求。

WebView.loadUrl( “关于:空白”)

您是否尝试过不在WebView中使用javascript?

我听说这可能是一个潜在的安全漏洞,它对WebView呈现网页有很好的影响。

祝你好运!

更新

看起来您的问题与您的网页浏览无关,但您的PHP脚本是否正确?

尝试在Java中使用此功能创建密码或检查用户密码是否正确时:

String password = "123456"; 
MessageDigest md = MessageDigest.getInstance("SHA-256"); 
md.update(password.getBytes()); 
byte byteData[] = md.digest();

您只需要在应用程序或服务器脚本的一侧执行此操作。我会从应用程序方面选择,因为这样您就可以通过网络而不是纯文本发送散列密码。

答案 1 :(得分:0)

我通过使用不同的散列函数解决了我的问题,它现在可以在所有设备上运行。我认为这是Android webview中的一些奇怪的错误。