2014-02-19 116 views
1

我一直在开发Android和iOS上的Web应用程序并使用Web视图。 iPhone上的一切工作都很好,但是在Android上它并不适用于所有设备,它让我疯狂。在五款Android设备上效果很好,但在两款设备上,它并没有超出登录页面。但它在浏览器中的移动网站(而不是应用程序)上工作。Android Webview,formhash无法在某些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> 

我不知道这是否是一个错误或东西。奇怪的是,它在大多数设备上都可以使用,但在某些设备上却不适用它也适用于浏览器,这让我觉得它与Android中的Web视图有关。我处于死胡同,感谢每一个帮助。谢谢!

更新 我终于找到了问题所在,它与形式散列有关。该密码在webview中的某些Android设备上给出了不同的sha512散列,这使得无法登录。不知道它是否是某些设备上Android Web视图的限制,有人知道如何解决这个问题吗?

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应用程序,机器人会浏览器,桌面浏览器或Android应用程式,它提供了一个sha5哈希使用:c7d9a2def4f8d0f9c4b65d7522566ed33549b266174b2b12ae7f7b047e7efed2e92d18e552d1c812f073e794d16feb8ccf9df85399c475f24571472dece2d9b2

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

a3e08c365ef82d4256d8e58fd63b53d63d50b6b3cac3cdaba395cc73289e5f955491f11f06408c2c6e6ae531d69ddb10f234ecef0cf375d9782abea27909c9ef

回答

1

我也有这个问题之前,我的WebView将无法在当前窗口中打开一个URL,很短的时间后,Android操作系统便拿起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

你可以看到我在My Github Project从226行开始处理这个问题,在那里我添加了一个扩展了WebViewClient类的额外的innerclass。

旁注

这工作在我的应用上,我支持大多数设备。但是你也可能想确保你的URL是完全合格的。我发现,当我使用任何URL没有

的http://

在它的面前,将网页视图无法加载的URL甚至与其他WebViewClient。对象和shouldOverrideUrlLoading()调用。

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

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

,你试过没有使用JavaScript的网页视图?

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

祝你好运!

UPDATE

它看起来像你的问题是不是与你的WebView但你的PHP脚本是否正确?

尝试使用这种从Java创建密码时,或检查,如果用户的密码是正确的:

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

你真的只需要做到这一侧或者您的应用程序或服务器脚本。我会从应用程序端选择,因为这样您可以通过网络发送散列密码而不是纯文本。

+0

谢谢,但我已经创建了一个名为DivumWebViewClient的附加webviewclient,如代码中所示。我也检查了http://,那也不成问题。几个小时后,我想我终于找到了问题。它与形式哈希和加密有关。有些Android设备会给出不同的哈希值,导致无法登录。仍然不知道如何解决它,但找到问题有很大帮助。 :) – Leonard

+0

您可以尝试将哈希函数更改为兼容Java和PHP的哈希函数,以便您可以在网络上传递加密密码并在您的PHP脚本中接收它。我相信sha-256会工作,或者sha-1,但那不太安全'String password =“123456”; MessageDigest md = MessageDigest.getInstance(“SHA-256”); md.update(password.getBytes()); byte byteData [] = md.digest();' –

+0

是的我已经使用了不同的哈希函数,它现在可以在所有设备上运行。我认为这是Android webview中的一种奇怪的错误。谢谢你的帮助! – Leonard

0

我已经通过使用不同的哈希函数解决了我的问题,它现在适用于所有设备。我认为这是Android webview中的一种奇怪的错误。

相关问题