I am trying to follow a online tutorial to create this login, but I receive this error. I tried this on localhost but it doesn't work on a server. Can anybody tell me what is my mistake please. Here's my code:
private void checkLogin(final String email, final String password) {
// Tag used to cancel the request
String tag_string_req = "req_login";
pDialog.setMessage("Logging in ...");
showDialog();
StringRequest strReq = new StringRequest(Method.POST,
AppConfig.URL_LOGIN, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d(TAG, "Login Response: " + response.toString());
hideDialog();
try {
JSONObject jObj = new JSONObject(response);
boolean error = jObj.getBoolean("error");
// Check for error node in json
if (!error) {
// user successfully logged in
// Create login session
session.setLogin(true);
// Now store the user in SQLite
String uid = jObj.getString("uid");
JSONObject user = jObj.getJSONObject("user");
String name = user.getString("name");
String email = user.getString("email");
String created_at = user
.getString("created_at");
// Inserting row in users table
db.addUser(name, email, uid, created_at);
// Launch main activity
Intent intent = new Intent(LoginActivity.this,
MainActivity.class);
startActivity(intent);
finish();
} else {
// Error in login. Get the error message
String errorMsg = jObj.getString("error_msg");
Toast.makeText(getApplicationContext(),
errorMsg, Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
// JSON error
e.printStackTrace();
Toast.makeText(getApplicationContext(), "Json error: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
}
It means either the response is not in JSON format or the client side did not get any response at all. Try to following steps.:-
1.Before using the URL in the application check it in a web browser if you are getting the desired response or not. If there is any server side error it will be displayed in the web browser.
2. Now check the serve side response with a JSON validator to check if the response is a valid JSON or not
3.If your server side is then use logcat or toast message to print your response and check the response.
I just found out the way to solve it. It's the codes in the DB_Functions.php file that caused the problem. I have changed the code a bit then it works now. Thanks so much you guys for the help.I have also attached the code in case someone ran into the same problem. Good luck guys
public function getUserByEmailAndPassword($email, $password) {
$result = mysqli_query($this->conn,"SELECT * FROM users WHERE email = '$email'") or die(mysqli_connect_errno());
// check for result
$no_of_rows = mysqli_num_rows($result);
if ($no_of_rows > 0) {
$result = mysqli_fetch_array($result);
$salt = $result['salt'];
$encrypted_password = $result['encrypted_password'];
$hash = $this->checkhashSSHA($salt, $password);
Related
I am trying to put in a delete account option in my application, however when I try to delete the account I am not getting a respsonse from the web server.
Instead I get the error:
org.json.JSONException: End of input at character 0 of
I have tried to change the request method to DELETE however I am not too familiar with android and databases so I am not sure if that would work.
I am not sure whether the problem lies with the php or the java code, when I run the debugger in android studio the String response returns:
response: ""
php:
<?php
if($_SERVER['REQUEST_METHOD']=='POST'){
$id = $_POST['id'];
require 'conn.php';
$sql = "DELETE * FROM Patients WHERE patientID='$id'";
if(mysqli_query($conn, $sql)){
$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);
}
}
?>
Java delete method:
private void deleteAccount() {
final String name = this.name.getText().toString().trim();
final String lName = this.lName.getText().toString().trim();
final String dob = this.dob.getText().toString().trim();
final String email = this.email.getText().toString().trim();
final String password = this.password.getText().toString().trim();
final String passwordConf = this.cPassword.getText().toString().trim();
final String id = getID;
StringRequest stringRequest = new StringRequest(Request.Method.POST, URL_DELETE,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jsonObject = new JSONObject(response);
String success = jsonObject.getString("success");
if(success.equals("1")){
Toast.makeText(EditAccount.this, "Account Deleted", Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
Toast.makeText(EditAccount.this, "Error: "+e.toString(), Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(EditAccount.this, "Error: "+error.toString(), Toast.LENGTH_SHORT).show();
}
})
{
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> params = new HashMap<>();
params.put("id", id);
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}
}
I expect the toast to pop up and say account deleted but instead I get the error message stated at the top.
p.s. this is just a prototype so I am not worried about security at the moment.
Thanks!
Whatever the issue might be, I am going to take a guess and say if($_SERVER['REQUEST_METHOD']=='POST') is the root of your issue.
Your request may be sent wrong to the server and the method is not recognized as POST which would explain a "" response since you do not offer an alternative to what should happen at the condition failing.
Send a bad request response (400) back and you will have the ability to troubleshoot this issue in your Java code... PHP is fine.
if($_SERVER['REQUEST_METHOD']=='POST') { /* ... */ }
else {
http_response_code(400);
// exit('Bad request method.');
// or for a json response:
echo json_encode([
'success' => "0",
'message' => "Bad Request Method used."
]);
}
Also, I have to say... Security should always be a concern... It does not take but a few more lines of code to filter the user request, and make your query a bit more secure via prepared statements. It's more of an issue of habits; one day you might forget a query here or there.
Could someone give me an advice , how can I get just one headers . Because I'm getting all of header , I can't choose just one. This is my code:
LoginService loginService =
RetrofitClient.createService(LoginService.class, userEmail, userPassword);
loginService.basicLogin(new Callback<User>()
{
#Override
public void success (User user, Response response){
List<retrofit.client.Header> tokens = response.getHeaders();
Log.e(LOG_TAG, "x-auth-token is" + xAuthToken));
Toast.makeText(getApplicationContext(), "Your are in", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(getApplicationContext(), BetweenActivity.class);
startActivity(intent);
}
If you want to use the first token, you can use:
retrofit.client.Header firstToken;
if (tokens.size() > 0) {
firstToken = tokens.get(0);
}
If you want to iterate through the tokens to find a specific one, you can use:
retrofit.client.Header token = null;
for (retrofit.client.Header tmpToken : tokens) {
if (tmpToken.foo()) {
token = tmpToken;
break;
}
}
I think that JSONException only works when it my request fails but when the request is valid (valid username, password) it should redirect me to another activity but instead a JSONException is showing up.
It shows the JSON string received from the server rather than redirecting me to another activity.
This is my onResponse function
#Override
public void onResponse(String response){
try {
JSONObject volleyResponse = new JSONObject(response);
boolean success = volleyResponse.getBoolean("success");
String message = volleyResponse.getString("message");
String UUID = volleyResponse.getString("unique_user_id");
String LLOGIN = volleyResponse.getString("last_login");
String RDATE = volleyResponse.getString("registration_date");
String MONEY = volleyResponse.getString("money");
if(success){
Intent intent = new Intent(Authentication.this, Mainpage.class);
intent.putExtra(KEY_USERNAME, strUsername);
intent.putExtra(KEY_UUID, UUID);
intent.putExtra(KEY_LLOGIN, LLOGIN);
intent.putExtra(KEY_RDATE, RDATE);
intent.putExtra(KEY_MONEY, MONEY);
startActivity(intent);
}
} catch(JSONException e) {
response = response.replace("\"", "");
response = response.replace("status:false,message:", "");
response = response.replace("{", "");
response = response.replace("}", "");
messageText.setText(response);
}
}
JSON Response when it is success:
{"unique_user_id":"4e99a28a-0cb2-30a9-ac51-ccd4629bcef1","last_name":"therealaxis","password":"$2a$10$9qRjW\/vJreCQg3u5dO6eW.8PhZBTpGaPNK5qRIYP.XTx2PVY1yrOi","last_login":"1 week ago","registration_date":"1 week ago","money":"100.00","success":true}
Your JSON Response has no message string, so a JSONException is thrown. If you just want to access the message attribute in case it is present, use JSONObject.has before accessing it.
I'm writing an android application which uses rest services for user regitration and more but running into trouble with my login service. for some reason the requestparams i put into my service call on android side are not being found within my rest service.
could anny 1 tell me what i'm doing wrong or link to a guide which explains how to solve this problem?
Relevant android functions:
public void loginUser(View view) {
// Get username and password values
String username = usernameEdit.getText().toString();
String password = passwordEdit.getText().toString();
// Instantiate Http Request Param Object
RequestParams params = new RequestParams();
// Check if username & password is not null
if(Utility.isNotNull(username) && Utility.isNotNull(password)) {
// Http parameters
params.put("username", username);
params.put("password", password);
invokeWS(params);
} else {
Toast.makeText(getApplicationContext(), "Vul een gebruikersnaam en of " +
"wachtwoord in", Toast.LENGTH_LONG).show();
}
}
// Method that performs RESTful webservice invocations
public void invokeWS(RequestParams params) {
// Make RESTful webservice call using AsyncHttpClient object
AsyncHttpClient client = new AsyncHttpClient();
client.post("http://10.0.2.2:8080/NTR_application/rest/session", params, new AsyncHttpResponseHandler() {
// When the response returned by REST has Http response code '200'
#Override
public void onSuccess(String response) {
Toast.makeText(getApplicationContext(), "You are successfully logged in!" + response, Toast.LENGTH_LONG).show();
// Gets an JSON object with user Data
// Write user Data to SQLite
User user = new Gson().fromJson(response, User.class);
db.addUser(user);
// Navigate to Home screen
navigatetoHomeActivity();
}
// When the response returned by REST has Http response code other than '200'
#Override
public void onFailure(int statusCode, Throwable error,
String content) {
Toast.makeText(getApplicationContext(), "ERROR!" + content + error + statusCode, Toast.LENGTH_LONG).show();
}
});
}
and the rest services which is called :
#Path("/session")
public class UserService {
private Controller controller = new Controller();
#POST //Post so you can't see the information in the browser history easily
#Produces(MediaType.APPLICATION_JSON)
public Response authenticate(#QueryParam("username") String username, #QueryParam("password") String password){
User user = null;
try {
user = controller.authenticate(username, password);
} catch (NoSuchAlgorithmException | SQLException e) {
System.out.println("Authentication caught an exception; failed for: " + username);
e.printStackTrace();
}
if (user != null){
String json = new Gson().toJson(user);
return Response.status(200).entity(json).build();
} else {
return Response.status(401).entity("Username and/or password is incorrect").build();
}
}
}
Mistake was obvious once i saw it, since i use a #POST i need to use #FormParam instead of #QueryParam.
tutorial i used to write these methods used #GET to login which is insecure.
so here is my issue: I am working on a mobile App, that requires a login. I am programming in Android Studio / Java. Got a quite good experience in Java but i've never done networking.. There is a .asp script on a server that processes the login, which i need to send the login data to. The best way to solve this i think is a HTTP - Request, because if you enter the url of the script into the browser, followed by the query string containing the login data, you already get a response.
http://sampleurl.info/actions/checklogin.asp?userName=klingenhaeger&password=droid&device=android
returns a Json String containing a profile token and a timestamp and the profile name.Like:
{"profil_token":"qn2hJcRQixYjG7yyW956g1407921902","profil_name":"Marc Klingenhäger","timestamp":"1407921902"}
This profile token is then attached to every url the user requests, and in that way the user gains permission to all the websites.
I read that you can do the same thing with a http GET request, but me and my coworker worked on this
(such a simple thing) for nine ours and didn't get our code working...
We tried out heaps of snippets, this is our most simple attempt:
In the Main activity, on clicking the button that leads to the login, LoginActivity.class is called using a Intent.
Intent intent = new Intent(this, LoginActivity.class);
startActivity(intent);
After entering the user data, the user clicks the login button, and the method attemptLogin(); gets called.
public void attemptLogin() {
if (mAuthTask != null) {
return;
}
// Reset errors.
mEmailView.setError(null);
mPasswordView.setError(null);
// Store values at the time of the login attempt.
String email = mEmailView.getText().toString();
String password = mPasswordView.getText().toString();
boolean cancel = false;
View focusView = null;
// Check for a valid password, if the user entered one.
if (!TextUtils.isEmpty(password) && !isPasswordValid(password)) {
mPasswordView.setError(getString(R.string.error_invalid_password));
focusView = mPasswordView;
cancel = true;
}
// Check for a valid email address.
if (TextUtils.isEmpty(email)) {
mEmailView.setError(getString(R.string.error_field_required));
focusView = mEmailView;
cancel = true;
} else if (!isEmailValid(email)) {
mEmailView.setError(getString(R.string.error_invalid_email));
focusView = mEmailView;
cancel = true;
}
if (cancel) {
// There was an error; don't attempt login and focus the first
// form field with an error.
focusView.requestFocus();
} else {
// Show a progress spinner, and kick off a background task to
// perform the user login attempt.
showProgress(true);
mAuthTask = new UserLoginTask(email, password);
mAuthTask.execute((Void) null);
}
}
So after some error detection, the class userLoginTask (subclass of AsyncTask) is initialized to handle the networking stuff, because initializing the http request in the main thread seems to cause an exception. We didn't manage to code a HTTP - Request here so far.. (thats the main problem)
public class UserLoginTask extends AsyncTask {
private final String mEmail;
private final String mPassword;
UserLoginTask(String email, String password) {
mEmail = email;
mPassword = password;
}
#Override
protected Boolean doInBackground(Void... params) {
// TODO: attempt authentication against a network service.
try {
// Simulate network access.
Thread.sleep(2000);
} catch (InterruptedException e) {
return false;
}
for (String credential : DUMMY_CREDENTIALS) {
String[] pieces = credential.split(":");
if (pieces[0].equals(mEmail)) {
// Account exists, return true if the password matches.
return pieces[1].equals(mPassword);
}
}
// TODO: register the new account here.
return true;
}
#Override
protected void onPostExecute(final Boolean success) {
mAuthTask = null;
showProgress(false);
if (success) {
finish();
} else {
mPasswordView.setError(getString(R.string.error_incorrect_password));
mPasswordView.requestFocus();
}
}
#Override
protected void onCancelled() {
mAuthTask = null;
showProgress(false);
}
}
So my question is basically, how can i initialize a HTTP - Request in the UserLoginTask class. Any Ideas? Thanks in advance! :)
Falco
The easiest way is to use a URL object and open a stream to your HTTP server.
The server response can be read through this stream:
String url = "http://sampleurl.info/actions/checklogin.asp?userName=klingenhaeger&password=droid&device=android";
try {
URL u = new URL(url);
InputStream is = u.openStream(); // Opens streaming connection to url
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuffer result = new StringBuffer(); // Buffer to store saved data
String input = null;
while((input = reader.readLine()) != null) {
// Read data until the end of the stream
result.append(input);
}
// Do something with result here
} catch (IOException e) {
e.printStackTrace();
}
When you have retrieved the data as a string, you can parse the JSON to get the profile_token
Use Android's Volley http://developer.android.com/training/volley/index.html and issue an HTTP POST request, sending username / password.
I advise hashing the password (MD5 or something else - depends on what the back-end handles to decrypt).
Google suggests using HttpUrlConnection.
An example that should do what you want is very simple, especially when using GET. First, construct an URL from String. Your response is InputStream, which you parse to JSONObject and obtain your token.
URL url = new URL("http://sampleurl.info/actions/checklogin.asp?userName=klingenhaeger&password=droid&device=android");
//later:
URL url = new URL("http://sampleurl.info/actions/checklogin.asp?token=abcde");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
readStream(in);
finally {
urlConnection.disconnect();
}
}
This is recommended approach, since it does not require any external libraries, and it can easily be converted to use POST instead of GET and HTTPS instead of HTTP.