I am working on a login/register app.
That's my Java Code in my MainActivity:
private void loginUser(){
pd = ProgressDialog.show(LoginActivity.this, "", "Loading...");
StringRequest stringRequest = new StringRequest(Request.Method.POST, LOGIN_URL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jsonResponse = new JSONObject(response);
System.out.println("JSON RESPONSE: " + jsonResponse.toString());
boolean success = jsonResponse.getBoolean("success");
if (success) {
launchHomeScreen();
pd.dismiss();
Toast.makeText(LoginActivity.this,"Welcome back " + username,Toast.LENGTH_LONG).show();
}
else {
Toast.makeText(LoginActivity.this,"Wrong Username or Password!",Toast.LENGTH_LONG).show();
pd.dismiss();
}
}
catch (JSONException e) {
e.printStackTrace();
pd.dismiss();
Toast.makeText(LoginActivity.this,response,Toast.LENGTH_LONG).show();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
pd.dismiss();
System.out.println("Error: " + error);
}
}){
#Override
protected Map<String,String> getParams(){
Map<String,String> params = new HashMap<>();
params.put(KEY_USERNAME,username);
params.put(KEY_PASSWORD,password);
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}
}
login.php:
<?php
$con = mysqli_connect("x", "x", "x", "x");
$username = $_POST["username"];
$password = $_POST["password"];
$statement = mysqli_prepare($con, "SELECT * FROM user WHERE username = ?");
mysqli_stmt_bind_param($statement, "s", $username);
mysqli_stmt_execute($statement);
mysqli_stmt_store_result($statement);
mysqli_stmt_bind_result($statement, $colUserID, $colUsername, $colPassword);
$response = array();
$response["success"] = false;
while(mysqli_stmt_fetch($statement)){
if (password_verify($password, $colPassword)) {
$response["success"] = true;
}
}
header('Content-Type: application/json');
echo json_encode($response);
?>
The mysql table looks like: user_id;username;passsword;mobilenumber;email
When i trying to login I get this back in Android logcat, so that error is caused by writting the LOGIN_URL wrong.
E/Volley: [251] BasicNetwork.performRequest: Unexpected response code 404 for http://myserver.xyz/pubic_html/login.php
I/System.out: Error: com.android.volley.ServerError
But there is another Error. I send the right logindatas to the server but everytime I get back success:false.
The weird thing is that I use a similar java code for registration (only with a register.php), and it works, so what is wrong?
This is register.php
<?php
$connect = mysqli_connect("localhost", "root", "", "user");
$username = $_POST["username"];
$password = $_POST["password"];
$hashedPassword = password_hash($password, PASSWORD_BCRYPT);
$mobilenumber = $_POST["mobilenumber"];
$email = $_POST["email"];
registerUser();
$response["success"] = false;
function registerUser() {
global $connect, $username, $hashedPassword, $mobilenumber, $email;
$statement = mysqli_prepare($connect, "INSERT INTO user (username, hashedPassword, mobilenumber, email) VALUES (?, ?, ?, ?)");
mysqli_stmt_bind_param($statement, "siss", $username, $hashedPassword, $mobilenumber, $email);
mysqli_stmt_execute($statement);
mysqli_stmt_close($statement);
$response["success"] = true;
}
header('Content-Type: application/json');
echo json_encode($response);
?>
404 means the app cannot find the login.php page. Make sure your path to the script is correct.
Try removing the "public_html" from the link. That is your root folder. You do not need to specify this in your link. It should work if you remove that.
EDIT
Since you edited your post after I answered that question, let me edit mine to answer your next. Judging from the password_very function in you php file, you are using password_hash and your password is encrypted with password_hash('yourPass', PASSWORD_BCRYPT);?
In this case, I do not see that you included the library in you PHP script. Just add the following line to your php file and it should work.
include('path/to/password_hash.php');
The problem is, because the file is not found, password_verify is not recognized. I am sure if you change $_POST['username'] and $_POST['password'] to 'YourUsername' and 'YourPassword' and run your file from a browser, you will see all errors, and that will be one of them.
Hope this helps!
EDIT 2
Since you are having issues with the password. In your statement where you insert the password to the database use the password_hash function to hash the password BEFORE you insert it to the database like so:
$hashedPassword = ('Yourpassword', PASSWORD_BCRYPT);
Do your MySQL query and add the $hashedPassword value to the database in the password field. Then retrieve the password and username like you did at the very beginning and use the password_verify function to match the passwords like so:
if (password_verify($_POST['password'], $hashedPassword) {
// Do your login stuff.
}
Now it should login. (Optional Extra) Also, try looking at PDO to do your sql queries. It is much better. To use PDO do the following:
//Initiate Connection
$conn = new PDO('mysql:host='.$db_host.';dbname='.$db_name, $db_user, $db_password);
$stmt = $conn->prepare("SELECT password FROM user WHERE username = :username");
if ($stmt->execute(array(':username' => $_POST['username']))) {
if ($result = $stmt->fetch(PDO::FETCH_ASSOC)) {
$passwordFromDb = $result['password']; //This is the password you match in password verify. This password should be hashed in the database. if it is hashed it will look something like this - $2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq.
}
}
The problem I think is that you have 'Geige' stored as your password in the database and not that hashed string. So when the password_verify function tries to match the passwords, it fails. Your code might be right, but the password in the database might be wrong. When inserting the password to the database, make sure you are hashing it and inserting the hashed password.
I really hope this helps.
EDIT 3 Register Rewrite
<?php
//Initiate Connection
$conn = new PDO('mysql:host='.$db_host.';dbname='.$db_name, $db_user, $db_password);
$username = $_POST["username"];
$password = $_POST["password"];
$hashedPassword = password_hash($password, PASSWORD_BCRYPT);
$mobilenumber = $_POST["mobilenumber"];
$email = $_POST["email"];
$stmt = $conn->prepare("INSERT INTO user (username, hashedPassword, mobilenumber, email) VALUES (:username, :password, :mobile, :email)");
if ($stmt->execute(array(':username' => $username, ':password' => $hashedPassword, ':mobile' => $mobilenumber, ':email' => $email))) {
$response["success"] = true;
} else {
$response["success"] = false;
}
header('Content-Type: application/json');
echo json_encode($response);
?>
Related
I have an Android app which writes/reads from an external SQL database through a PHP script. Both the database and the PHP script is hosted on Amazon Web Services (AWS). The app sends HTTP request to the PHP script, and the PHP script communicates with the database.
Are there easier ways to connect the app with the database? I feel like this method is kinda hacky. Or is this how it is done? Is it possible to avoid the PHP script entirely and just communicate with the database through Java in the app?
Below is the code for fetching everything in the database.
The php script:
$servername = "";
$username = "";
$password = "";
$conn = mysqli_connect($servername, $username, $password);
if (!$conn) {
die("Connection failed: " . mysqli_connect_error());
}
$sql = "SELECT * FROM table";
$result = $conn->query($sql);
if($result->num_rows > 0){
while($row = $result->fetch_assoc()){
echo "rowname1: " . $row["rowname1"]. " rowname2: " . $row["rowname2"] . "\n";
}
} else {
echo "0 results";
}
$conn->close();
The Java code:
requestQueue = Volley.newRequestQueue(this);
String url = "";
StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
textDatabase.setText(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
textDatabase.setText(error.toString());
}
});
requestQueue.add(stringRequest);
This is the correct way to do that, via API.
Frontend Application (Android, iOS, browser) <-> API <-> Backend
You can connect direct to the database, but you should not. To be able to do that, you have to put user and password in your application. Doing this, how do you prevent users to connect on your database and changing all they want? There are many more points against this approach.
Look for REST APIs, or maybe GraphQL.
I'm working on an application that registers users in a database of a domain I have. I developed it using Android Studio, and I'm having some problems handling the users info to the php file using the POST method.
The main problem I have is that my app returns a success while transfering the data to the database, but when I look at it it's empty.
Here's my Java code:
package com.test.application;
import com.android.volley.Response;
import com.android.volley.toolbox.StringRequest;
import java.util.HashMap;
import java.util.Map;
public class RegisterRequest extends StringRequest {
private static final String REGISTER_REQUEST_URL="http://www.mywebsite.com/Register.php";
private Map<String,String> params;
public RegisterRequest(String user, String password, String email, Response.Listener<String> listener){
super(Method.POST, REGISTER_REQUEST_URL, listener, null);
params = new HashMap<>();
params.put("name", user);
params.put("password", password);
params.put("useremail", email);
}
#Override
public Map<String, String> getParams() {
return params;
}
}
and here's my PHP code that recieves the data:
<?php
$con = mysqli_connect("bbdd.mywebsite.com", "user", "password", "database");
$Username = $_POST["name"];
$Password = $_POST["password"];
$UserEmail = $_POST["useremail"];
$statement = mysqli_prepare($con, "INSERT INTO AccountsInfo (Username, Password, UserEmail) VALUES (?, ?, ?)");
mysqli_stmt_bind_param($statement, "ssis", $Username, $Password, $UserEmail);
mysqli_stmt_execute($statement);
$response = array();
$response["success"] = true;
echo json_encode($response);
?>
Assuming everything else is correct, your parameter type specification in the bind call has an i (integer) that doesn't match any parameter. For 3 string parameters, you'll want to use sss:
mysqli_stmt_bind_param($statement, "sss", $Username, $Password, $UserEmail);
You should enable error reporting so that things don't just fail silently. See
how to get a detailed error report when a php-mysql script fails?
I am trying to get hold of a JSONArray by using StringRequest in Android along with the POST-method.
The php-script is written like:
$statement = mysqli_prepare($con, "SELECT * FROM tickets WHERE user_id > 5 AND completed = 1");
mysqli_stmt_bind_param($statement, "i", $UID);
mysqli_stmt_execute($statement);
mysqli_stmt_store_result($statement);
mysqli_stmt_bind_result($statement, $user_id, $beacon_id, $timeFrom, $timeTo, $completed);
$jsonObject = array();
$response = array();
while($status = mysqli_stmt_fetch($statement)){
$jsonObject = null;
$jsonObject["beacon_id"]= $beacon_id;
$jsonObject["timeFrom"]= $timeFrom;
$jsonObject["timeTo"]= $timeTo;
$response[] = $jsonObject;
}
echo json_encode($response);?>
Accessing the web-page with the php-script, the following JSONArray is "echoed":
[{"beacon_id":10,"timeFrom":"2018-02-14 13:07:11","timeTo":"2018-02-14 14:32:53"},{"beacon_id":3,"timeFrom":"2018-02-24 13:33:37","timeTo":"2018-02-24 13:33:47"}]
And as I understand this is a normal JSONArray with square-brackets representing the array and curly-brackets for each JSONObject inside the array.
When I try to access this JSONArray through a StringRequest in Android Studio (Java), I do not get any results...
The StringRequest code:
public class HistoryRequest extends StringRequest {
private static final String HISTORY_REQUEST_URL = "http://myURL.../myPHPfile.php";
private Map<String, String> params;
public HistoryRequest(String user_id, String instanceID, Response.Listener<String> listener) {
super(Method.POST, HISTORY_REQUEST_URL, listener, null);
params = new HashMap<>();
params.put("user_id", user_id);
params.put("instanceID", instanceID);
}
#Override
public Map<String, String> getParams() {return params;}
}
The ResponseListener in the MainActivity is written like:
Response.Listener<String> responseListener = new Response.Listener<String>() {
#Override
public void onResponse(String response) {
JSONArray jsonArray = new JSONArray(response);
for(int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
String timeFrom = jsonObject.getString("timeFrom");
String timeTo = jsonObject.getString("timeTo");
textviewFrom.append(timeFrom);
textviewTo.append(timeTo);
}
}
};
Any tips why I can't make a JSONArray of the String that in the web-page URL looks like a beautiful JSONArray?
Thanks in advance!
UPDATE:
After switching to JSONArrayRequest instead of StringRequest, I can get the data if I change the MySQL part of the php-script to something static like:
SELECT * FROM tickets;
Then I can display all the entries. But I tend to send 1 parameter to the server (user_id), so that I can filter the entries based on the user that is logged in. [SELECT * FROM tickets where user_id = ?], like a traditional POST-method....
Someone who knows what to do? Read several places that you can not #Override the getParams()-method for this...
SOLVED:
I solved the issue by entering the keyvalue (user_id) into the URL.
//Instead of POST:
$user_id = $_POST["user_id"];
// I use SERVER to get the value after ? in the URL:
$user_id = $_SERVER['QUERY_STRING'];
Doing this with the following java-code:
public class HistoryRequest extends JsonArrayRequest {
private static final String HISTORY_REQUEST_URL = "http://myURLorIPaddress/getHistory.php?";
public HistoryRequest(String UID, Response.Listener<JSONArray> listener) throws JSONException {
super(Method.POST, HISTORY_REQUEST_URL + UID,null, listener, null);
}
}
This made it possible to filter the result based on user_id and works like a charm :D
I do not get to print anything, but I can see that the Volley library is complaining for some external errors (nothing referred to my code). The log.i("OnResponseLog", response) does not provide anything.
Picture of error from LogCat:
I am working in similar project did you check if there are some null entries? I think the problem might be there by checking your LogCat picture.
Check using isNull() function might be good idea.
https://processing.org/reference/JSONObject_isNull_.html
I am trying to convert a PHP-array into a Java ArrayList.
I have this PHP-Code which seems to have no syntax errors:
$password = "xxxx";
$host = "localhost";
$db_name = "xxxx";
$output = array();
$con = mysqli_connect("$host", "$user", "$password");
if (!$con)
{
die('Could not connect: ' . mysql_error());
}
if (!mysqli_select_db($con, $db_name)) {
die('Could not select database: ');
}
$result = mysqli_query($con, "SELECT name FROM shopping_items"); //change to "name"
if (!$result) {
printf("Error: %s\n", mysqli_error($con));
exit();
}
while($row = mysqli_fetch_array($result, MYSQLI_BOTH))
{
$output[]=$row;
}
return $output;
mysqli_close($con);
?>
It takes one row from the table, so I should get back a PHP-array.
Now comes the hard part. In Java, I wrote the following code using the Volley library:
public void getShopping(String url) {
//init queue or get from somewhere
RequestQueue queue = Volley.newRequestQueue(this);
StringRequest stringRequest;
stringRequest = new StringRequest(Request.Method.GET, url, //URL leads to PHP-File
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
shoppingItems.add(response); //shopping Items is an ArrayList
adapter.notifyDataSetChanged();
Toast.makeText(ShoppingListActivity.this, response, Toast.LENGTH_SHORT);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//got error
}
});
queue.add(stringRequest);
}
I want to have each item added to shoppingItems. But when printing the array out I get an empty string. I think that StringRequest is the wrong way to go but I don't know any other way. I read that using json_encode is possible but that seems unnecessarily complicated to me. Is there an easier way to do that?
I could not find an answer in previous SO questions. If at all possible, please provide help that involves Volley because it is pretty integrated in my code.
I am trying to connect my libGDX(java) android project with a mySQL database through a server side PHP scripting in order to implement a login process using POST method (this includes a username and password).
Therefore, i am facing unexpectable problems. For your info i am using XAMPP and APACHE web server locally.
What i am facing! Some times the PHP script sends back the following response string, as if not recognizing the POST parameters (despite the fact that POST message includes them and contain values (string)!!):
<b>Notice</b>: Undefined index: username in <b>C:\xampp\htdocs\login\login.php</b> on line <b>5</b><br />
<br />
<b>Notice</b>: Undefined index: password in <b>C:\xampp\htdocs\login\login.php</b> on line <b>6</b><br />
Some other, the debugger (on Android studio) which is enabled to show me the debugging logs, stops displaying any log after pressing 2-5 times the btnclickLogin() (is shown below), which implements the login activity.
This sounds to me that http connection hangs up and maybe the click button's listener does not respones any more!!!
The more strange one, is that SOMETIMES the same code, returns "success" and everything works fine.
The android code is the next
private void btnclickLogin() {
//Getting values from edit texts
Gdx.app.setLogLevel(Application.LOG_DEBUG);
final String username = usernamefld.getText().toString().trim();
final String password = passwordfld.getText().toString().trim();
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("username", username);
parameters.put("password", password);
Gdx.app.debug("Login process started.", "Username=/" + username + "/ Password=/" + password + "/");
HttpRequestBuilder requestBuilder = new HttpRequestBuilder();
HttpRequest httpRequest;
httpRequest = requestBuilder.newRequest().method(Net.HttpMethods.POST).url("http://192.168.1.2/login/login.php").content(HttpParametersUtils.convertHttpParameters(parameters)).build();
httpRequest.setHeader("Content-Type", "application/x-www-form-urlencoded");
httpRequest.setTimeOut(6000);
Gdx.net.sendHttpRequest(httpRequest, new HttpResponseListener() {
#Override
public void handleHttpResponse(Net.HttpResponse httpResponse) {
String status = httpResponse.getResultAsString().trim();
Gdx.app.debug("Return result by the server=", status);
if(status.contains("success"))
game.setScreen(new StartingScreen(game));
}
#Override
public void failed(Throwable t) {
String status = "failed";
Gdx.app.debug("Connection failed due to the next error:", t.getMessage());
}
#Override
public void cancelled() {
}
});
httpRequest.reset();
Gdx.app.debug("Exiting", "From login button function");
}
PHP scripts are
For login.php
<?php
if($_SERVER['REQUEST_METHOD']=='POST'){
//Getting values
session_start();
$username = $_POST['username'];
$password = $_POST['password'];
//Creating sql query
$sql = "SELECT * FROM users WHERE username='$username' AND password='$password'";
//importing dbConnect.php script
require_once('dbConnect.php');
//executing query
$result = mysqli_query($con,$sql);
//fetching result
$check = mysqli_fetch_array($result);
//if we got some result
if(isset($check)){
//displaying success
echo "success";
}else{
//displaying failure
echo "failure";
}
mysqli_close($con); }?>
For dbConnect.php
<?php
define('HOST',"localhost");
define('USER',"root");
define('PASS',"");
define('DB',"userlogging");
$con = mysqli_connect(HOST,USER,PASS,DB) or die('Connection failed: ' . $conn->connect_error);
$con->set_charset("utf8"); ?>
Please give a hand to overcome this problem and make the http connection "stable"!!
Thanks a lot.
Mishra sorry for the latest of my reply.
Yes, actually i have placed a print_r to see the values that come up to PHP script and found that both parameters were missing.
After so much searches on the internet and alternative solutions that found, i have not found out why does it happen. So, i replaced the HttpRequestBuilder.
Finally, in order to have a complete working code, i used the next and everything works fine now.
final String username = usernamefld.getText().toString().trim();
final String password = passwordfld.getText().toString().trim();
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("username", username);
parameters.put("password", password);
final HttpRequest httpRequest = new HttpRequest(Net.HttpMethods.POST);
httpRequest.setHeader("Content-Type", "application/x-www-form-urlencoded");
httpRequest.setHeader("Upgrade", "HTTP/1.1, HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11");
httpRequest.setUrl(LOGIN_URL);
httpRequest.setContent(HttpParametersUtils.convertHttpParameters(parameters));
httpRequest.setTimeOut(6000);
Thanks again for your help.