API call using angular 7 doesn't read PHP session variables - php

I need to create simple login with angular and use sessions.
for that i've two php files and angular files.
This is PHP file 1
session_start();
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: PUT, GET, POST, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
$postdata = file_get_contents("php://input");
if(isset($postdata) && !empty($postdata)) {
$request = json_decode($postdata);
$username=trim($request->username);
$password=trim($request->password);
if($username == 'admin' && $password == 'admin') {
$_SESSION['user'] = 'admin';
?>
{
"success": true,
"secret": "This is the secret no one knows but the admin"
}
<?php
} else {
?>
{
"success": false,
"message": "Invalid credentials"
}
<?php
}
} else {
//var_dump($_POST)
?>
{
"success": false,
"message": "Only POST access accepted"
}
<?php
}
?>
This is PHP file 2
<?php
session_start();
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: PUT, GET, POST, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
$user = $_SESSION['user'];
echo '{
"message": "'.$user.'",
"success": true
}';
?>
In one of my component's ngOnInit(), i've called both of these APIs (i know first one should be triggered in a login submit button, but for testing purpose i've used both under one.). I have even used settimeout function to delay the second call
ngOnInit() {
this.auth.getUserDetails('admin','admin')
.subscribe(
data => {
console.log('success',data);
if(data.success){
}
else{
window.alert("invalid");
}
},
error=> {
console.log('failed',error);
}
)
var _this=this;
setTimeout(function(){
_this.user.getSomeData().subscribe(data=>{
console.log(data);
})
}, 3000);
}
But still user session is unavailable.. I need help to understand the reason.
Please check the image.
For first post request is success and but second get request is failed.
It says session variable i used (user) is not available.
But that variable has been set by previous request.
This is the error i get
Thank you

I had the same issue working on React and PHP locally, both using localhost but on different ports. This answer helped me.
PHP sessions are stored on cookies, and when making cross-domain (or in this case cross-port) requests those cookies are not shared.
In your first login call to PHP, you need to return the session ID using session_id() and store this somewhere on your app. Then, when making further calls to PHP, make sure to pass it the same session id. You can then use session_id() again to set the id to the one you passed, which will keep the last session active:
if ($request->session_id) {
session_id($request->session_id);
}
start_session();
$json['session_id'] = session_id();
$json['user'] = $_SESSION['user'];
echo json_encode($json);

You are Working on Two Different Server localhost:80 for PHP and Localhost:4200 for angular so your request for a session is Localhost:4200 This request can not access PHP session.
so please set headers in angular for the PHP side request.

Related

How to enable or Allow Access-Control-Allow-Origin for JQuery and Codeigniter 4

I'm building an API to activate and validate active installations of my PHP Scripts,
but I get the "Access to XMLHttpRequest at 'http://api.domain.te/requests/verify' from origin 'http://domain.te' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource" error on console.
Here is my jQuery code:
function verify() {
$.post(url+"requests/verify", {
domain: domain
}, function(data) {
if (data.success === true) {
return true;
}
});
return false;
}
I have read through similar questions and tried all the suggestions, but none seems to be working.
On my PHP code I have:
public function verify()
{
$data['success'] = false;
$data['status'] = 'error';
$data['message'] = 'An error occurred';
if ($this->actives_m->check($this->request->getPost("domain")??""))
{
$data['success'] = true;
$data['status'] = 'success';
$data['message'] = 'Product is Active!';
}
else
{
$data['message'] = 'Product is Inactive!';
}
$this->response->setHeader('Access-Control-Allow-Origin', '*');
$this->response->setHeader('Access-Control-Allow-Methods', 'GET, POST');
return $this->response->setJSON($data);
}
I have also tried setting the headers at the beginning of the script after <?php but still did not work.
I also tried the built in PHP header() function like so:
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST');
I have even modified my JS to look like:
function verify() {
$.ajax({
url: url+"requests/verify",
type: "POST",
dataType: "JSON",
data: {domain: domain},
crossDomain: true,
success: function(data) {
if (data.success === true) {
return true;
}
}
});
return false;
}
So far nothing seems to be working, Where should I go from here?
UPDATE:
I realize that if I use Pure Javascript like:
const xhr = new XMLHttpRequest();
xhr.open('GET', url+"requests/verify");
xhr.onreadystatechange = function(data) {
if (data.success === true) {
return true;
}
}
xhr.send();
It works as expected, but I have to use jQuery to keep my code uniform, and for future reference.
Whenever, there is a cross-origin issue, there are two routes that are hit. Lets say in your example, you have GET request to "http://api.domain.te/requests/verify", So before hitting your server with GET request it will hit same url with OPTIONS request. This verifies whether your server allows the API for the Cross Origin Request.
So In CI4 routes you have to define same URL or include a wild card to enable your cross origin request.
Here, the following example is for wild card request.
$routes->options('(:any)', 'Controller/options');
Here this route matches any routes with OPTIONS method and a single method called Options is there to handle it.
This options method can be defined as follows :
public function options($any)
{
return $this->response->setHeader('Access-Control-Allow-Origin', '*') //for allow any domain, insecure
->setHeader('Access-Control-Allow-Headers', '*') //for allow any headers, insecure
->setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE') //method allowed
->setStatusCode(200); //status code
}
What this method essentially does is lets the browser know that request are allowed for Cross-Origin, with status Methods such as GET, POST, PUT and DELETE.
After browser hits this request, it will be directed to your request which should also have cross origin enabled as follow:
$this->response->setContentType('application/json')->setJSON($response)->send()->setHeader('Access-Control-Allow-Origin', '*');
Reference : https://carminemilieni.it/2019/09/19/resolve-cors-and-corb-in-codeigniter-4/
As you already do, CORS must be approached from the receiving server side, so I put headers from .htaccess in Apache sites (check how to do it if you use different server):
Header set Access-Control-Allow-Origin "*"
(in your case, it should be a * if can be multiple unknown domains)
Header set Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept"
(or the method ones if you want too)
Info and options on that header:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
You can check what headers are you sending out by using curl, do they appear?
curl -I http://api.domain.te/requests/verify

PHP api sends HTTP_response_code(400) no matter what

i wrote a Simple PHP crud api and i'm getting HTTP_response_code(400) no matter what i do.
in the api a file named create.php is responsible for inserting new items in the database it checks if the data it receives from ajax isn't empty and then proceeds to creation if it's empty it sends an HTTP_response_code(400).
but, no matter what i do it always sends the HTTP_response_code(400) even though the data is not empty.
i thought the problem was coming from ajax first but after debugging i found out that ajax in facts gets the proper data from the form and sends it.
here is my create.php file
$db = $database->getConnection();
$consumable = new consumable($db);
//get json
$json = file_get_contents("php://input");
// get posted data
$data = json_decode($json);
// make sure data is not empty
if(
!empty($data->reference) &&
!empty($data->price) &&
!empty($data->description) &&
!empty($data->category_id) &&
!empty($data->quantity)
){
// set consumable property values
$consumable->reference = $data->reference;
$consumable->price = $data->price;
$consumable->description = $data->description;
$consumable->category_id = $data->category_id;
$consumable->quantity = $data->quantity;
$consumable->created = date('Y-m-d H:i:s');
// create the consumable
if($consumable->create()){
// set response code - 201 created
http_response_code(201);
// tell the user
echo json_encode(array("message" => "consumable was created."));
}
// if unable to create the consumable, tell the user
else{
// set response code - 503 service unavailable
http_response_code(503);
// tell the user
echo json_encode(array("message" => "Unable to create consumable."));
}
}
else{
// tell the user data is incomplete
// set response code - 400 bad request
//http_response_code(400);
// tell the user
echo json_encode(array("message" => "Unable to create consumable. Data is incomplete."));
echo json_encode($json);
}
and here is my ajax:
$(document).on('submit', '#create-consumable-form', function(){
alert("submit");
// get form data
var form=$(this).serializeObject();
var form_data=JSON.stringify(form);
console.log('a',form);
console.log(form_data);
// submit form data to api
$.ajax({
url: "http://localhost:3000/consumable/create.php",
type : "POST",
contentType : 'application/json',
data : form_data,
success : function(result) {
// consumable was created, go back to consumables list
showconsumables();
},
error: function(xhr, resp, text) {
// show error to console
console.log(xhr, resp, text);
}
});
return false;
});
after filling out the form and submitting instead of adding the entry to the database and sending a 201 OK it shows me the following error:
jquery.js:2 OPTIONS http://localhost:3000/consumable/create.php 400 (Bad Request)
send # jquery.js:2
ajax # jquery.js:2
(anonymous) # create-consumables.js:87
dispatch # jquery.js:2
v.handle # jquery.js:2
index.html:1 Access to XMLHttpRequest at 'http://localhost:3000/consumable/create.php' from origin 'http://localhost:5500' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
and this is the result of my console.log
a {reference: "BT3000", price: "10", quantity: "5", description: "description", category_id: "3"}
create-consumables.js:85 {"reference":"BT3000","price":"10","quantity":"5","description":"description","category_id":"3"}
the weird thing is when i comment the HTTP_response_code(400) line in my create.php file it works perfectly does anyone have any idea of the cause of this behaviour?
Try to put header() in your create.php file:
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Max-Age: 3600");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
json_decode returns null if it cannot decode it. It seems it does just that. Maybe you need to url_decode and/or stripslashes the contents before you can decode it. As Ahmed is saying, try to output the $data variable and the output of the json_decode and file_get_contents("php://input"); and you will see the mistake soon enough.
Also be aware that !empty(0) and !empty(false) returns true. So if your variable has a value which is 0 or false then it will return 400 in this case as well. This is not the issue in your example, but might become an issue later.
the problem was caused by the fact that the content-type in my headers was application/json and i was using postman for testing and i had left it to default content-type which is text

ReactJS and PHP Sessions [duplicate]

I am using Fetch Api in my application.
I've got a PHP server page to get session data which was already defined before. It seemd like this:
<?php
header('Content-Type: application/json; charset=UTF-8');
header('Access-Control-Allow-Origin: *');
session_start();
// $_SESSION['data'] already defined before
$result = array();
// print_r($_SESSION['data']);
if (isset($_SESSION['data'])) {
$result = $_SESSION['data'];
$result['code'] = 'ok';
} else {
$result['code'] = 'error';
}
echo json_encode($result, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
I also got another html page to get the session data. It seemd like this:
<script>
$(function() {
// use $.ajax
$.ajax({
url: 'session.php',
dataType: 'json'
})
.done(function(res) {
console.log(res);
});
// end
// use fetch
fetch('session.php').then(function(res) {
if (res.ok) {
res.json().then(function(obj) {
console.log(obj);
});
}
});
// end
});
</script>
The problem is, when I use $.ajax(), session data can be correctly showed. But when I use fetch(), the session data was undefined.
So, what goes wrong and how can I fix it? Thanks!
If you want fetch to send cookies, you have to provide the credentials option.
See https://developer.mozilla.org/en-US/docs/Web/API/GlobalFetch/fetch#Parameters for details.
jquery ajax is a usual ajax request and the browser is sending the cookie header with the session id that identify your session.
fetch doesnt - instead a new session is created with out any data
send the php session id either with url or header
have a look at: http://php.net/manual/en/session.idpassing.php

How to create cookie or session through jquery ajax?

I'm trying to build own javascript API for a chat online. This API is intended to get css file and javascript file and after loading the website it must create a conversation window. I want to share this API for other users.
e.g. If my domain is mydomain.com and includes in html code my javascript API, which downloads css file and javascript file from example.com, what is the best practice to create cookie or session on the user side?
Below is my API:
<div id="fb-dialog"></div>
<script async defer src="http://coders.localhost/api/fb-dialog.js">
var apiConf = {
key: 'YOUR_API_KEY',
language: {
/* Your language codes and default greeting */
"pl" : "Dzień dobry, jestem online. W czym mogę pomóc?",
"en" : "Hello, I'm online. How can I help you?"
}
}
</script>
I want share this chat but any conversation must be save on my server.
I want to use a database which will to have a website's ID on the which is installed the API. Before starting a conversation in cookie I want get website ID on the which can I will return response. How can I to do?
My javascript:
<script>
$.ajax({
xhrFields: {
withCredentials: true
},
type: "GET",
url: "http://coders.localhost/modules/fb-dialog/heading.php"
}).done(function (data) {
alert("OK");
});
</script>
My PHP script:
<?php
if (!isset($_SERVER['HTTP_ORIGIN'])) {
// This is not cross-domain request
exit;
}
$wildcard = false; // Set $wildcard to TRUE if you do not plan to check or limit the domains
$credentials = true; // Set $credentials to TRUE if expects credential requests (Cookies, Authentication, SSL certificates)
$allowedOrigins = array('http://firma.localhost', 'http://jsfiddle.net');
if (!in_array($_SERVER['HTTP_ORIGIN'], $allowedOrigins) && !$wildcard) {
// Origin is not allowed
exit;
}
$origin = $wildcard && !$credentials ? '*' : $_SERVER['HTTP_ORIGIN'];
header("Access-Control-Allow-Origin: " . $origin);
if ($credentials) {
header("Access-Control-Allow-Credentials: true");
}
header("Access-Control-Allow-Methods: POST, GET, OPTIONS");
header("Access-Control-Allow-Headers: Origin");
header('P3P: CP="CAO PSA OUR"'); // Makes IE to support cookies
// Handling the Preflight
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
exit;
}
if(!isset($_COOKIE['fb-dialog'])) {
setcookie("fb-dialog", "true", time()+3600, "/");
}else{
if(!isset($_POST['data'])) {
if($_COOKIE['fb-dialog'] == 'true') {
setcookie('fb-dialog', 'false', 0, '/');
} else {
setcookie("fb-dialog", "true", time()+3600, "/");
}
}
}
// Response
header("Content-Type: application/json; charset=utf-8");
echo json_encode(array('status' => 'OK'));
?>
The above code is working. I'm getting a status 200 but a cookie is not for proper domain because the script create a cookie for domain coders.localhost
I have two domains:
http://firma.localhost - this is my website
http://coders.localhost - this is remote domain from who I get API
I want create cookie by coders.localhost domain for firma.localhost.
You can also use plain javascript:
document.cookie = "username=admin";
or
var x = document.cookie;
Probably you have figured already the answer, It would be great if you shared how you resolved it.
I think the issue maybe due to your / configuration in the setcookie
Your config:
setcookie("fb-dialog", "true", time()+3600, "/");
Try this:
setcookie("fb-dialog", "true", time()+3600, "http://coders.localhost");

Cross-Domain jQuery.Ajax request - Chrome extension

I would like to realize an Google Chrome extension, which would show a notification following the result of an Ajax request.
I coded the function which allows to create a notification, so I just have to do the Ajax request which fetches a .php file on a remote server which belongs to me. This request just failed, nothing happened. Nevertheless when I try to realize the request since my server towards my server (without the extension), no problem, I deducted from it that it was a problem of "Cross-Domain"...
Here are the important elements (for the problem) of the manifest.json (I just put all possible permissions^^) :
{
"background": {
"scripts": ["myScript.js", "jquery-2.1.4.min.js"]
},
"manifest_version": 2,
"permissions": [ "http://*/", "https://*/" , "http://*/*" , "https://*/*", "tabs", "notifications", "browsingData", "webRequest", "webNavigation" ],
...
...
}
Here is the AJax request in myScript.js :
(The spawnNotification function works perfectly, tested without the request)
$.ajax({
url: "http://www.domain.com/test/get.php",
type: "GET",
crossDomain : true,
success: function() {
spawnNotification("Title", "work", "img/notif.png", "http://www.domain.cor/forum/");
},
error: function() {
spawnNotification("Title", "error", "img/notif.png", "http://www.domain.co/forum/");
}
});
And finally, the get.php file :
<?php
header("Content-Type: text/plain");
header("Access-Control-Allow-Origin: *");
$str = 15;
echo $str;
?>
What am I doing wrong here? Thanks !
 
( Here are some topics that did not help me...
Chrome extension Cross Domain Request
Chrome extension xhr cross domain request gives error:"is not allowed by Access-Control-Allow-Origin." )
You need to provide more response headers than just that one, see the Cross-Origin Resource Sharing specification for details.
Here's pseudo-code (from my other answer here) of what's required in your server code (sorry, don't write much PHP, hence pseudo-code):
// Find out what the request is asking for
corsOrigin = get_request_header("Origin")
corsMethod = get_request_header("Access-Control-Request-Method")
corsHeaders = get_request_header("Access-Control-Request-Headers")
if corsOrigin is null or "null" {
// Requests from a `file://` path seem to come through without an
// origin or with "null" (literally) as the origin.
// In my case, for testing, I wanted to allow those and so I output
// "*", but you may want to go another way.
corsOrigin = "*"
}
// Decide whether to accept that request with those headers
// If so:
// Respond with headers saying what's allowed (here we're just echoing what they
// asked for, except we may be using "*" [all] instead of the actual origin for
// the "Access-Control-Allow-Origin" one)
set_response_header("Access-Control-Allow-Origin", corsOrigin)
set_response_header("Access-Control-Allow-Methods", corsMethod)
set_response_header("Access-Control-Allow-Headers", corsHeaders)
if the HTTP request method is "OPTIONS" {
// Done, no body in response to OPTIONS
stop
}
// Process the GET or POST here; output the body of the response
#T.J. Crowder
Thanks Crowder, I tried to write it in PHP and I first tried that for my get.php :
<?php
header("Content-Type: text/plain");
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST');
header("Access-Control-Allow-Headers: X-Requested-With");
$str = 15;
echo $str;
?>
It doesn't work so I searched a bit with what you said, and found that https://stackoverflow.com/a/9866124/5733765
get.php :
<?php
if (isset($_SERVER['HTTP_ORIGIN'])) {
header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Max-Age: 86400');
}
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");
exit(0);
}
$str = 15;
echo $str;
?>
But still doesn't work
I found the problem... we have to use xhr
myScript.js :
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://domain.com/test/get.php", true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
alert(xhr.responseText);
}
}
xhr.send();
Thanks for your help ;)
EDIT: the real problem was to define jquery.js after in the myScript.js
manifest.json:
"background": {
"scripts": ["jquery-2.1.4.min.js", "notification.js"]
},

Categories