0

why nothing happened when i put the correct email, but whatevet i put correct or incorrect password the program still not doing anything. It's like the program not checked the password, can you help me ?

This my login.php

    <?php

    if ($_SERVER['REQUEST_METHOD']=='POST') {

        $email = $_POST['email'];
        $password = $_POST['password'];

        require_once 'connect.php';

        $sql = "SELECT * FROM user WHERE email='$email' ";

        $response = mysqli_query($conn, $sql);

        $result = array();
        $result['login'] = array();

        if ( mysqli_num_rows($response) === 1 ) {
            $row = mysqli_fetch_assoc($response);


            if ( password_verify($password, $row['password']) ) { // I Think The Problem At This but i still don't know.
                echo $password;

                $index['name'] = $row['name'];
                $index['email'] = $row['email'];
                $index['id'] = $row['id'];

                array_push($result['login'], $index);

                $result['success'] = "1";
                $result['message'] = "success";
                echo json_encode($result);

                mysqli_close($conn);

            } else {

                $result['success'] = "0";
                $result['message'] = "error";
                echo json_encode($result);

                mysqli_close($conn);

            }

        }

    }

    ?>

This my SignInActivity.java // or at this the problem is ?

public class SignInActivity extends AppCompatActivity {

    private EditText email,password;
    private Button login;
    private TextView link_regist;
    private static String URL_LOGIN = "https://awalspace.com/app/imbalopunyajangandiganggu/login.php";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sign_in);

        email = findViewById(R.id.titEmail);
        password = findViewById(R.id.titPassword);
        login = findViewById(R.id.btnSignIn);
        link_regist = findViewById(R.id.tvToSignUp);

        login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String mEmail = email.getText().toString().trim();
                String mPassword = password.getText().toString().trim();

                if(!mEmail.isEmpty() || !mPassword.isEmpty())
                {
                    login(mEmail,mPassword);
                }
                else{
                    email.setError("Silahkan Masukkan Email");
                    password.setError("Silahkan Masukkan Password");
                }
            }
        });
    }

    private void login(final String email, final String password) {
        StringRequest stringRequest = new StringRequest(Request.Method.POST, URL_LOGIN,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        try {
                            JSONObject jsonObject = new JSONObject(response);
                            String success = jsonObject.getString("success");
                            JSONArray jsonArray =jsonObject.getJSONArray("login");

                            if (success.equals("1")){
                                for (int i = 0; i < jsonArray.length(); i++){
                                    JSONObject object = jsonArray.getJSONObject(i);

                                    String name = object.getString("name").trim();
                                    String email = object.getString("email").trim();
                                    Toast.makeText(SignInActivity.this, "Success Login. \n Your Name : "+name+"\nYour Email : "+email,Toast.LENGTH_SHORT).show();
                                }
                            }
                        } catch (JSONException e) {
                            e.printStackTrace();
                            Toast.makeText(SignInActivity.this, "Error "+e.toString(),Toast.LENGTH_SHORT).show();
                        }
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Toast.makeText(SignInActivity.this, "Error "+error.toString(),Toast.LENGTH_SHORT).show();
                    }
                })
        {
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                Map<String, String> params = new HashMap<>();
                params.put("email",email);
                params.put("password",password);
                return params;
            }
        };
        RequestQueue requestQueue = Volley.newRequestQueue(this);
        requestQueue.add(stringRequest);
    }
}
computercarguy
  • 2,173
  • 1
  • 13
  • 27
  • **Warning:** You are wide open to [SQL Injections](https://php.net/manual/en/security.database.sql-injection.php) and should use parameterized **prepared statements** instead of manually building your queries. They are provided by [PDO](https://php.net/manual/pdo.prepared-statements.php) or by [MySQLi](https://php.net/manual/mysqli.quickstart.prepared-statements.php). Never trust any kind of input! Even when your queries are executed only by trusted users, [you are still in risk of corrupting your data](http://bobby-tables.com/). [Escaping is not enough!](https://stackoverflow.com/q/5741187) – Dharman Nov 01 '19 at 21:12
  • **WARNING**: Writing your own access control layer is not easy and there are many opportunities to get it severely wrong. Please, do not write your own authentication system when any modern [development framework](https://www.cloudways.com/blog/best-php-frameworks/) like [Laravel](http://laravel.com/) comes with a robust [authentication system](https://laravel.com/docs/master/authentication) built-in. – tadman Nov 01 '19 at 22:22

1 Answers1

1

Partial answer:

First off

You are open to SQL injection. You should parameterize your query.

Parameterized queries in PHP with MySQL connection

Second

You can add the password to your query so you don't have to do a 2nd check, if you store the passed password in the DB, or you can hash your password first then use it in your query. That avoids getting more user data than necessary (with the associated possible leaking of data) and avoids needing a second method to find the correct user. This is shown in the link above.

If you store a salt in the DB, I can understand why you need the 2nd method, but you might be able to salt the password in the SQL, via a SQL function. Since you don't include the code for password_verify, we have no way to know what you're actually doing there, so I'm keeping this as basic as I can. (My philosophy is to keep things simple until complications are required.)

Third

Even if you are getting all the columns in that table, specify the column names you need. You might end up adding to that table later, which would cause this query to pull more data than it needs, again.

Fourth

Since you already have the email, which is one of the parameters of the query, you don't need to get it from the DB.

FYI, the link above adds each parameter individually, but mysqli_stmt_bind_param can do them all in one shot.

Object oriented style

mysqli_stmt::bind_param ( string $types , mixed &$var1 [, mixed &$... ] ) : bool

Procedural style

mysqli_stmt_bind_param ( mysqli_stmt $stmt , string $types , mixed &$var1 [, mixed &$... ] ) : bool
...
types

A string that contains one or more characters which specify the types for the corresponding bind variables:
...

https://www.php.net/manual/en/mysqli-stmt.bind-param.php

$stmt = mysqli_prepare($dbc, "SELECT name, id FROM users WHERE email= ? AND password = ?");
mysqli_stmt_bind_param($stmt, "ss", $email, $password); // or use a hash from a method instead of $password
mysqli_stmt_execute($stmt);
$row = mysqli_stmt_fetch($stmt);

This should pull just the one user, unless it doesn't pull any users, so you should have a clear indication of whether this user has access to your site/data/whatever or not. I would suggest sending an actual success message that you can recognize as something a little more specific to you, rather than the generic message you have right now. I understand you're still in testing phase, so it's something to think about later, if you hadn't already.

I would also suggest sending an HTTP 401 message back if $row is null. That way it's 100% guaranteed that your client software understands what happened as well as not giving any specifics as to why it failed. You can still tell the user something more meaningful, such as "Email and Password Combination Not Recognized". Also, don't specify if the email or the password is wrong, since this can lead to easier brute force hacking. There's a lot of contention around this idea of prompts, so I'll let you do your own research and make up your mind about it.

Whether your Java code is correctly sending the login credentials to your PHP server, IDK. I'm rusty on that, so I'll let someone else chime in, and why I'm saying this is a partial answer. At least this answer should get your PHP on the right track.

Community
  • 1
  • 1
computercarguy
  • 2,173
  • 1
  • 13
  • 27
  • i have used your code, but i get much error. Can you take you way to my php code pls @computercarguy – Gyroth Games Nov 01 '19 at 21:56
  • You'll likely need to add global variable `$dbc` and make your `connect.php` set up that variable for the SQL connection, or it's your current `$conn`. Without knowing what errors you're getting, I have no way to fix them. – computercarguy Nov 01 '19 at 22:12
  • [01-Nov-2019 22:17:19 UTC] PHP Warning: mysqli_stmt_bind_param(): Number of variables doesn't match number of parameters in prepared statement in /home/u7922769/public_html/app/imbalopunyajangandiganggu/login.php on line 20. https://codeshare.io/5QXOQx this my newer code – Gyroth Games Nov 01 '19 at 22:18
  • Note: [`password_verify`](https://www.php.net/manual/en/function.password-verify.php) is a PHP built-in function. No source is required. – tadman Nov 01 '19 at 22:22
  • It's also worth pointing out here that when you run [`password_hash`](https://www.php.net/manual/en/function.password-hash.php) you get a value that's non-reversible. It's also different each time you run it, by design, so you can't create a look-up table of hashed passwords. This means you cannot do a `SELECT * FROM users WHERE name=? AND password=?`. In the original code the record is pulled and `password_verify` is run on it, which is the correct way of testing. – tadman Nov 01 '19 at 22:30
  • You make a few good points here. One thing I'd object to is even mentioning the PHP4-era `mysqli` procedural style. It's way more verbose and also easily confused with `mysql_query` functions of the same name. All it takes is a missing `i`. – tadman Nov 01 '19 at 22:31
  • 1
    @tadman, I basically copied and modified the code from the first link. I wasn't even thinking about the OO vs. functional style, but yes, doing it in the newer methods is much better, not to mention less likely to be deprecated in the near future. And feel free to make your own Answer without the caveats my answer seems to need. – computercarguy Nov 01 '19 at 23:39
  • @GyrothGames, you need to replace the `'$email'` and `'$password'` with `?` as in what I have in the Answer. They don't need to be named, just in the same order. The `?` are markers that will get replaced in order, so you don't even need the single quotes for strings. https://stackoverflow.com/questions/14781051/php-mysqi-bind-param-number-of-variables-doesnt-match-number-of-parameters-in-p – computercarguy Nov 01 '19 at 23:52