How to create simply REST API Login? - mysql

I've trying to create login code in REST Server and while I use POSTMAN to check it, the output always show HTTP_BAD_REQUEST(Login Failed). The code is ignoring security.
I use REST from https://github.com/chriskacerguis/codeigniter-restserver
This is My Controller
public function index_post(){
$data_memb = array(
'id_member'=>$this->post('id_member'),
'password'=>$this->post('password')
);
$result = $this->Member_model_api->loginMember($data_memb);
if ($result == TRUE) {
$this->response([
'status' => true,
'message' => 'Login Successfull'
], REST_Controller::HTTP_OK);
} else {
$this->response([
'status' => false,
'message' => 'Login Failed'
], REST_Controller::HTTP_BAD_REQUEST);
}
}
}
This is My Model
public function loginMember($data_memb)
{
$sql = 'SELECT * FROM member WHERE id_member = ?';
$binds = array($data_memb['id_member']);
$query = $this->db->query($sql, $binds);
if ($query->num_rows()>0) {
$rw_password = $query->result();
if (password_verify($data_memb['password'],
$rw_password[0]->password)) {
return true;
} else {
return false;
}
} else {
return false;
}
}
I expect the output is HTTP_OK(Login Successfull), or if you have more reference code, please tell me. Thanks for your help.

Since you are using POST method, you should use form-data while sending request.
I assume there may be some re-formatting issue on the server-side which might be preventing your login functionality to get verified.
Try printing both variables on the server-side and view the output.
var_dump($data_memb)
Nothing needs to send urlencoded in POST request.
Try changing the request type and see, this will work.

Related

Redirect restfull api codeigniter

I want to ask how to redirect the results from the input code form post like this
how do i redirect resfull api I want after input_post () page will be redirected
public function loginsi_post(){
$username = $this->post('username');
$password = $this->post('password');
$data = [];
$data['username'] = $username;
$data['password'] = $password;
if ($this->model_app->insert('jajal', $data) > 0) {
$this->response([
'message' => 'data berhasil disimpan',
'data' => $data
], REST_Controller::HTTP_CREATED);
}else{
$this->response([
'message' => 'data gagal disimpan'
], REST_Controller::HTTP_CREATED);
}
redirect('main/home'); ---------> is not working
}
Please setup your route like as below.
public function index() {
/*Load the URL helper*/
$this->load->helper('url');
/*Redirect the user to some site*/
redirect('http://www.example.com');
}
Best Regards.
Note: One can not access any controller that is in other folder and script access is not allowed this way. So there must be route set in route.php then you can access the function using route path. It can be defined as below:-
Like for example:- In route.php, the route is defined as:-
$route['your uri']='your uri';
then to access controller :-
$captcha_url = "http://your_api_url/index.php/nlpgen/nlpimg/"
Now you can use CURL to access the external URL.

yii2 retrieve passwordHash for AccessTokenByUser

for use in Mobile App, I am trying to use Yii2 built in RestApi.
Now what I understand by the reading that we should disable session and set loginUrl property to false.
Now what I want is, I want a login screen for my app and want to authenticate against API.
how I can achieve the same.
Note:
I can authenticate with username and password for different controllers including users controller as well as bearer token.
also I read an example in" yii2 by example"
public function actionAccessTokenByUser($username, $passwordHash)
{
$accessToken = null;
$user = \app\models\User::findOne(['username' => $username, 'password_hash' => $passwordHash]);
//var_dump($passwordHash1);exit;
if($user!=null)
{
$user->access_token = Yii::$app->security->generateRandomString();
$user->save();
$accessToken = $user->access_token;
}
return [ 'access-token' => $accessToken ];
}
my question is how I get the `$passwordHash to supply here. I tried to look back and forth, but couldn't find any solution.
my main purpose is how I can implement a application login for mobile and thereon supply the accesstoken in the background wherever needed.
I believe I have refactored the code to achieve what I am looking. Open to suggestion or any flaw in my implementation.
here is what I have done.
public function actionAccessTokenByUser($username, $password)
{
$accessToken = null;
$username = \app\models\User::findByUsername($username);
if ($username!=null)
{
if($username->validatePassword($password)) $user = $username;
}
// $user = \app\models\User::findOne(['username' => $username, 'password_hash' => $passwordHash]);
if($user!=null)
{
$user->access_token = Yii::$app->security->generateRandomString();
$user->save();
$accessToken = $user->access_token;
}
return [ 'access-token' => $accessToken ];
}

not responding while login

I am new to CodeIgniter, and am trying to write code to log in after registering using a username and password in registration form using a PHPMyAdmin database. I am not getting anything when I try to log in, and it doesn't display an error or any message.
public function login() {
$this->form_validation->set_rules('username','Username','required');
$this->form_validation->set_rules('password' , 'Password');
if($this->form_validation->run() == TRUE){
//check user in database
$this->db->select('username' , 'password');
$this->db->from('user_register');
$this->db->where(array('username' => $username, 'password' => $password));
$query = $this->db->get();
$user = $query->row();
if($user->email){
$this->session->set_flashdata("Successful login");
$_SESSION['user_logged'] = TRUE;
$_SESSION['username'] = $user->username;
} else {
$this->session->set_flashdata("Error No such record found");
}
}
// load view and showing login form
$this->load->view('login');
}
First, you should read the documentation, looks like you skip that part, but it's very important!
Let's code a little bit and fix the bugs!
User data
Well, users will enter their data and we will check, if evertyhing is correct, we can redirect user to the protected page. You call for variables (see Query:) but you I'm not seeing on your code. You should put like that, before your query job
$username = $this->input->post("username");
$password = $this->input->post("password");
Now, you will be able to use the where to get the user data. =)
Query:
If read about OOP with PHP, you know that when you pass parameters to a method, each parameter have their own "action". In case of the select method, you should keep the data you want to select, on the same quote, because you the way you do, it's like you passing multiple parameters to the method.
$this->db->select('username, password');
$this->db->from('user_register');
$this->db->where(array('username' => $username, 'password' => $password));
First, to decide if the record exist or not, I prefer this way:
if($query->num_rows() > 0) {
$user_data = $query->row();
// We should verify if the user entered the password that correspond to the account.
// If not, we tell them that the password is incorrect.
if($password != $user_data->password) {
$this->session->set_flashdata("error", "Wrong password!");
return redirect(site_url());
}
// You can use the CI built in methods to work with sessions
$this->session->set_userdata(array(
'username' => $user_data->username,
));
$this->session->set_flashdata("success", "You are logged in!");
return redirect(site_url());
} else {
$this->session->set_flashdata("Error: No such record found");
redirect(site_url());
}
Flash data
Yeah, we use flashdata to show a message for the user. But, you should pass an item and the value of this item. Like that:
$this->session->set_flashdata('success', 'Successfully logged in!");
And, to retrieve the data on your views, you can do like...
<?php
$success = $this->session->flashdata("success");
$error = $this->session->flashdata("error");
if(!empty($success)) {
echo $success;
}
if(!empty($success)) {
echo $error;
}
?>
Recommendations
Sessions: https://codeigniter.com/userguide3/libraries/sessions.html
Database: https://www.codeigniter.com/userguide3/database/query_builder.html
Also, I recommed you, to take a minute on YouTube, to understand CodeIgniter.
If I forgot something, let me know! =)
Great Suggestion by webmasterdro's Answer.
I would like to extend it a little bit.
Looking at your code it looks like you have added the query to the controller.
And as a suggestion, if you are using an MVC framework then try to follow some basic MVC flow. because if you are not following that then it will be useless to use a framework.
User Controller to handle the post data and validations.
Use model to do the database query.
Use __construct for loading the common model or libraries.
Do not save plane password use md5 or other encryption technique.
Store User detail to the session which you can use further in after login.
Codeigniter has a great user guide. Try to follow that.
So, your code Should be your like this below.
Controller:
public function __construct() {
parent::__construct();
// Load model
$this->load->model('login_database');
}
public function your_controller_function_name() {
// Check validation for user input in SignUp form
$this->form_validation->set_rules('username', 'Username', 'trim|required|xss_clean');
$this->form_validation->set_rules('password', 'Password', 'trim|required|xss_clean');
if ($this->form_validation->run() == FALSE) {
$this->load->view('login_form_view');
} else {
$username = $this->input->post("username");
$password = $this->input->post("password");
$result = $this->login_database->registration_insert($username, $password);
//You can do this also if($result != FALSE)
if (!empty($result)) {
// You can set other data to the session also form here
$session_data = array(
'username' => $result['user_name']
);
// Add user data in session
$this->session->set_userdata('logged_in', $session_data);
// You can set flash data here
$this->load->view('your_view');
} else {
$data = array(
'error_message' => 'Invalid Username or Password'
);
$this->load->view('your_login_form_view', $data);
}
}
}
Model:
// Read data using username and password
public function login($username, $password) {
$this->db->select('username');
$this->db->from('user_register');
$this->db->where(array('username' => $username, 'password' => $password));
$query = $this->db->get();
$user_data = $query->row_array();
if ($query->num_rows() == 1) {
return user_data;
} else {
return false;
}
}
I have not added detail related to flash data because the previous answer has explained it properly.

Cakephp3: How can I return json data?

I am having a ajax post call to a cakePhp Controller:
$.ajax({
type: "POST",
url: 'locations/add',
data: {
abbreviation: $(jqInputs[0]).val(),
description: $(jqInputs[1]).val()
},
success: function (response) {
if(response.status === "success") {
// do something with response.message or whatever other data on success
console.log('success');
} else if(response.status === "error") {
// do something with response.message or whatever other data on error
console.log('error');
}
}
});
When I try this I get the following error message:
Controller actions can only return Cake\Network\Response or null.
Within the AppController I have this
$this->loadComponent('RequestHandler');
enabled.
the Controller function looks like this:
public function add()
{
$this->autoRender = false; // avoid to render view
$location = $this->Locations->newEntity();
if ($this->request->is('post')) {
$location = $this->Locations->patchEntity($location, $this->request->data);
if ($this->Locations->save($location)) {
//$this->Flash->success(__('The location has been saved.'));
//return $this->redirect(['action' => 'index']);
return json_encode(array('result' => 'success'));
} else {
//$this->Flash->error(__('The location could not be saved. Please, try again.'));
return json_encode(array('result' => 'error'));
}
}
$this->set(compact('location'));
$this->set('_serialize', ['location']);
}
What do I miss here? Is there any additional settings needed?
Instead of returning the json_encode result, set the response body with that result and return it back.
public function add()
{
$this->autoRender = false; // avoid to render view
$location = $this->Locations->newEntity();
if ($this->request->is('post')) {
$location = $this->Locations->patchEntity($location, $this->request->data);
if ($this->Locations->save($location)) {
//$this->Flash->success(__('The location has been saved.'));
//return $this->redirect(['action' => 'index']);
$resultJ = json_encode(array('result' => 'success'));
$this->response->type('json');
$this->response->body($resultJ);
return $this->response;
} else {
//$this->Flash->error(__('The location could not be saved. Please, try again.'));
$resultJ = json_encode(array('result' => 'error', 'errors' => $location->errors()));
$this->response->type('json');
$this->response->body($resultJ);
return $this->response;
}
}
$this->set(compact('location'));
$this->set('_serialize', ['location']);
}
Edit (credit to #Warren Sergent)
Since CakePHP 3.4, we should use
return $this->response->withType("application/json")->withStringBody(json_encode($result));
Instead of :
$this->response->type('json');
$this->response->body($resultJ);
return $this->response;
CakePHP Documentation
Most answers I've seen here are either outdated, overloaded with unnecessary information, or rely on withBody(), which feels workaround-ish and not a CakePHP way.
Here's what worked for me instead:
$my_results = ['foo'=>'bar'];
$this->set([
'my_response' => $my_results,
'_serialize' => 'my_response',
]);
$this->RequestHandler->renderAs($this, 'json');
More info on RequestHandler. Seemingly it's not getting deprecated anytime soon.
UPDATE: CakePHP 4
$this->set(['my_response' => $my_results]);
$this->viewBuilder()->setOption('serialize', true);
$this->RequestHandler->renderAs($this, 'json');
More info
there are few things to return JSON response:
load RequestHandler component
set rendering mode as json
set content type
set required data
define _serialize value
for example you can move first 3 steps to some method in parent controller class:
protected function setJsonResponse(){
$this->loadComponent('RequestHandler');
$this->RequestHandler->renderAs($this, 'json');
$this->response->type('application/json');
}
later in your controller you should call that method, and set required data;
if ($this->request->is('post')) {
$location = $this->Locations->patchEntity($location, $this->request->data);
$success = $this->Locations->save($location);
$result = [ 'result' => $success ? 'success' : 'error' ];
$this->setJsonResponse();
$this->set(['result' => $result, '_serialize' => 'result']);
}
also it looks like you should also check for request->is('ajax); I'm not sure about returning json in case of GET request, so setJsonResponse method is called within if-post block;
in your ajax-call success handler you should check result field value:
success: function (response) {
if(response.result == "success") {
console.log('success');
}
else if(response.result === "error") {
console.log('error');
}
}
In the latest version of CakePHP $this->response->type() and $this->response->body() are deprecated.
Instead you should use $this->response->withType() and $this->response->withStringBody()
E.g:
(this was pinched from the accepted answer)
if ($this->request->is('post')) {
$location = $this->Locations->patchEntity($location, $this->request->data);
if ($this->Locations->save($location)) {
//$this->Flash->success(__('The location has been saved.'));
//return $this->redirect(['action' => 'index']);
$resultJ = json_encode(array('result' => 'success'));
$this->response = $this->response
->withType('application/json') // Here
->withStringBody($resultJ) // and here
return $this->response;
}
}
Relevant Documentation
When you return JSON data you need to define the data type and response body information like below:
$cardInformation = json_encode($cardData);
$this->response->type('json');
$this->response->body($cardInformation);
return $this->response;
In you case just change this return json_encode(array('result' => 'success')); line with below code:
$responseResult = json_encode(array('result' => 'success'));
$this->response->type('json');
$this->response->body($responseResult);
return $this->response;
RequestHandler is not required to send json.
In controller's action:
$this->viewBuilder()->setClassName('Json');
$result = ['result' => $success ? 'success' : 'error'];
$this->set($result);
$this->set('_serialize', array_keys($result));
As of cakePHP 4.x.x the following should work assuming that your controller and routes are set as shown below:
controller: <your_project_name>/src/Controller/StudentsController.php
public function index()
{
$students = $this->Students->find('all');
$this->set(compact('students'));
$this->viewBuilder()->setOption('serialize',['students']);
}
Routes: <your_project_name>/config/routes.php
<?php
use Cake\Routing\Route\DashedRoute;
use Cake\Routing\RouteBuilder;
/** #var \Cake\Routing\RouteBuilder $routes */
$routes->setRouteClass(DashedRoute::class);
$routes->scope('/', function (RouteBuilder $builder) {
$builder->setExtensions(['json']);
$builder->resources('Students');
$builder->fallbacks();
});
Run bin/cake server and visit http://localhost:8765/students.json using postman/insomnia or just the normal browser.
See further documentation for setting up Restful controllers and Restful Routing
Don't forget to set the method to GET on postman and insomnia.
Though I'm not a CakePHP Guru, in my case i'm using cake > 4 and I need some results by ajax call. For this, from my controller i wrote,
echo json_encode(Dashboard::recentDealers()); die;
and in my JS file i just need to parse the data using
JSON.parse(data)
The ajax call like
$.get('/recent-dealers', function (data, status) {
console.log (JSON.parse(data)); });
});

How to avoid the instruction "return" inside a function in Symfony2?

I would like to know how to avoid the instruction "return" inside a function in Symfony2. In other words how can I make a void function which doesn't return anything. In fact I have tried that for a long time but every time I run the code I did I see this error message: "The controller must return a response" ... By the way, this is the code that I have:
public function AddeventsgroupeAction(Request $request) {
$eventg = new eventsgroupe();
$form = $this->createForm(new eventsgroupeType(), $eventg);
$em = $this->getDoctrine()->getManager();
$securityContext = $this->get('security.context');
$token = $securityContext->getToken();
$user = $token->getUser();
$id = $user->getId();
$groupe=$this->getRequest('groupe');
$idg = intval($groupe->attributes->get('id'));
$qb = $em->createQueryBuilder();
$qb->select('l')
->from('IkprojGroupeBundle:Groupe', 'l')
->from('IkprojGroupeBundle:eventsgroupe', 'e')
->where(' l.id = :g and e.idGroupe = l.idAdmin and l.id = e.idEventGroupe');
$qb->setParameter("g", $idg);
$query = $qb->getQuery();
$res = $query->getResult();
$rows = array();
foreach ($res as $obj) {
$rows[] = array(
'id' => $obj->getId());
}
if ($request->isMethod('POST')) {
$form->handleRequest($request);
if ($form->isValid()) {
$eventg-> setIdGroupe($id);
$eventg-> setIdEventGroupe($idg);
$em->persist($eventg);
$em->flush();
return $moslem="yes";
}
} else {
return $this->render('IkprojGroupeBundle:GroupeEvents:Addeventgroupe.html.twig', array(
'groupe' => $rows,
'event' => $eventg,
'form' => $form->createView(),
));
}
}
How can I replace the instruction : return $moslem="yes"; in order to not return anything??...Is that possible??
To answer your basic question, a simple return will return a void from your function.
The "controller must return a response" message actually comes from the request handler. You need to tell the request handler what you want it to do. There is no default page so a void return will trigger the error.
In most cases, after successfully processing a posted form you will want to return a redirect response.
Something like:
$form->handleRequest($request);
if ($form->isValid()) {
...
$em->flush();
return $this->redirect($this->generateUrl('task_success'));
I should point out that your form code seems to be from S2.1 or older. It's unnecessarily complicated. You should be using at least 2.3. Make sure you are looking at the correct version of the documentation. Hint: the isValid() takes care of the POST check.
http://symfony.com/doc/current/book/forms.html#handling-form-submissions
It's also worth while to understand the request/response workflow.
http://symfony.com/doc/current/book/http_fundamentals.html
Digging into the code can also help in understanding where the error message is coming from:
Symfony\Component\HttpKernel\HttpKernel#handleRaw($request)
Simple, delete the else statement and if $request->isMethod('POST') or $form->isValid() returns false the code inside will not be executed then the script return the default view.
EDIT: you can also make a redirect with a flash message where needed like this:
$this->get('session')->getFlashBag()->add('success', 'your success message');
return $this->redirect($this->generateUrl('your_route'));
Remember to add support for flash message in your view looking at the Symfony2 docs