I hope someone can advise / direct / shed some light on :
i have a rails application that uses Authlogic for authentication.
i would like to incorporate cometchat into this application - (in reality any chat IM would do - but cometchat seemed to fit nicely because ajax-im does not like windows)
The environment is the following : The rails app is running on a windows machine - and will be available to the local network (no internet)
So to be able to use cometchat - i am running the WAMP server.
Into the nitty gritty of php(which i dont know well at all)
authlogic keeps my user session for me.
but for cometchat to work i need to pass the getUserID function the current user.
(comet chat assumes that there is a php session variable - but i dont have this with rails)
So how can i pass the rails session user to the getUserID function.
the function looks like this:
*function getUserID() {
$userid = 0;
if (!empty($_SESSION['userid'])) {
$userid = $_SESSION['userid'];
}
return $userid;
}*
the next function has to do with the friends list - but im sure this can be solved with sql inside the php page once i have the current user.
Again - all and any guidance is welcome here. Even if it means an alternate chat solution.
Many thanks in advance.
akza,
You can store the userid(numeric, non-zero, unique preferably the primary key from your users table) of currently logged-in user in a cookie say 'userid_for_cometchat'
and can access it as $_COOKIE['userid_for_cometchat'] in PHP
So your getUserID() should look like:
function getUserID() {
$userid = 0;
if (!empty($_COOKIE['userid_for_cometchat'])) {
$userid = $_COOKIE['userid_for_cometchat'];
}
return $userid;
}
You need to create this cookie on login and make sure to destroy it on logout.
This should work well.
CometChat Support team is real great at doing such stuff and they have performed a lot of custom modifications for me and I'm really satisfied by their job.
Related
I have an application that i built in php 7 with the code-igniter framework and my problem is with the session data , storing and retrieving session data works fine , but occasionally when two people log in at close intervals , the session data for the first user is also retrieved for the second user, searched through the site , saw something similar here (wrong data in PHP session) that suggested that it might be a caching issue (my site uses nginx for caching) , but no concrete solutions were suggested. Any suggestions or Ideas will be appreciated.
Edit : Here is the section of my login library for authentication
public function login_account($email,$password)
{
$db = "db";
$data = array("login_mail" => sha1($email));
$query_result = $this->CI->m_eauth->get_login_password($data,$db);
$hash_password ="";
foreach($query_result->result_array() as $value)
{
$hash_password = $value['hash_password'];
$site_name = $value['hash_name'];
$account_type = $value['account_type'];
$site_match_id = $value['site_match_id'];
$site_levels = $value['levels'];
$site_roles = $value['roles'];
}
if(password_verify($password, $hash_password)){
// Success!
$session_data = array(
"site_id"=>$site_match_id,
"site_email"=>$email,
"site_name"=>$site_name,
"site_avatar"=>md5($email).".jpg",
"site_type"=>$account_type,
"site_levels"=>$site_levels,
"site_roles"=>$site_roles
);
$this->CI->session->set_userdata($session_data);
return "successful";
}
else{
// Invalid credentials
return "unsuccessful";
}
}
Let me add that the login works fine and individual sessions work just fine. But every now and then the problem i described happens , and i'ts quite confusing as i don't know where to look.
There's no real way to sugar coat this, sessions aren't some magical part of PHP that you enable you to just call session_start() and go about your day. If your application is leaking sessions then you haven't secured it properly and you need to fix it.
Session security is a pretty big deal, given that a hijacked session basically gives an attacker total access to someone else's account.
I would recommend you read the official PHP session docs and also consider implementing the Nginx userid module as an additional measure for identifying users.
I am developing a PHP REST api using Api Platform for my website where users can post 'Reviews' (similar to articles).I want to track unique page views for this articles so I can later sort by most viewed reviews and display them.
I have read a lot of solutions online and I have implemented two of them: Google Analytics tracking and Redis + browser fingerprinting.
First, the Google Analytics tracking works quite well, I am using the 'ga:uniquePageviews' property with a filter for the page path to get using the Google PHP Api the unique page views. The only problem with this method is that some users use ad blockers and they block Google Analytics so no page view will be recorded for those people.
I have also implemented view tracking using Redis + browser fingerprinting (using fingerprintjs2) for anonymous users, and using the user id for logged in users. So for logged in users, if they have not visited the page in the last 30 minutes, a new unique view is added. This seems to work quite well.
The problem is with anonymous users. Currently, on the website side I am using fingerprintjs2 library to generate a browser fingerprint which is then passed to the REST api in a header and if that fingerprint did not visit the page in the last 30 minutes, then a new unique view is added. But because my REST api is going to be public (I plan on maybe also making a mobile app in the future), anyone can just put whatever then want in the fingerprint header and just keep changing it and a new unique view will be recorded and I am not sure how to fix this. Would allowing CORS only from my website domain fix this?But then what about the mobile app?
Right now I am inclined to think that using Google Analytics is the best way despite ad blockers, but the Redis approach just seems pretty cool to me and I would also like to get that working.
Here is a code example of what I am currently using for Redis:
public function addAndGetReviewViews(Request $request, $id)
{
$viewsKey = 'pageviews-review-' . $id;
$setKey = 'uniqueviews-review-' . $id;
$user = $this->getUser();
if ($user) {
$userId = $user->getId();
} else if ($request->headers->has('X-Anonymous-Fingerprint')) {
$userId = base64_encode(
substr($request->headers->get('X-Anonymous-Fingerprint'), 0, 32)
);
} else {
// Only add views if user is logged in or has anonymous fingerprint
return $this->redis->get($viewsKey) ?: 0;
}
$setExists = $this->redis->exists($setKey);
if (!$this->redis->sismember($setKey, $userId)) {
$this->redis->sadd($setKey, $userId);
$this->redis->incr($viewsKey);
}
if (!$setExists) {
$this->redis->expire($setKey, 1800);
}
return $this->redis->get($viewsKey);
}
I'm developing a mobile app which has to access to an external webapp (PHP + Codeigniter) to administrate the actions queried by ajax.
So by this way, there is a problem. If anyone see the urls used, could delete rows, or modify the user's info from the database. So I thought in this system to aboid this:
After a sucessful login I would do this:
// getToken : https://stackoverflow.com/a/13733588/2154101
$this->session->set_userdata('private_token', getToken(50));
$public_token = getToken(50);
$this->session->set_userdata('secure_token', md5("$private_token:$public_token"));
$data['token'] = $public_token;
// some stuff ...
// send $data in JSON
Then the client would the public token in the next query I would do this on the server:
$public_token = $this->input->post('token');
$data['token'] = get_public_token($public_token);
// some stuff ...
// send $data in JSON
Where get_public_token is within a helper with this code:
public get_public_token($public_token) {
$last_secure_token = $this->session->userdata('secure_token');
$private_token = $this->session->userdata('private_token');
$actual_token = md5("$private_token:$public_token");
if ($actual_token === $last_secure_token) {
$public_token = getToken(50);
$this->session->set_data('private_token', getToken(50));
$this->session->set_data('secure_token', md5("$private_token:$public_token"));
return $public_token;
} else { // you are cheating me ...
$this->session->sess_destroy();
redirect('/');
}
}
So only the user of this session could modify the data of the database.
I'm just trying to do the same explained here: https://stackoverflow.com/a/17371101/2154101
The session are encrypted, and I store them in a database too.
Do you think this method will work ok? Am I missing something important?
You should create an API for your mobile application. Create a authentication mechanism.
If your database holds user specific data, then you should create account for each user. So if the user sniffs the network and tries to call the api manually, then he could only change he's own data.
There are some API libraries for php out there, you should look into that.
Actually your solution is doing more than necessary. The only token of interest is the public_token sent back and forth. So you can throw away private_token and secure_token from session data, keeping only public_token for checking. Your current check is something like (X + 5)/2 == (14 + 5)/2 (is [received_token + 5]/2 equal to [14 + 5]/2 ?) when you can simplify to X == 14.
However if someone is sniffing the network, he can get the last token sent to a client and use it to hijack into that session. He can execute anything while the original client doesn't send a request with the outdated token, killing the session.
A better solution would be creating a secure_key after login and keep it at both ends (client and server). Then server would keep sending a new public_token at each response, but the client would send a md5(secure_key + public_token) at requests. This would narrow even more the hijacking window to the exact point where the session started. Without the original key, attackers can't create a valid md5.
However we are talking about minor hacking fans here. Anyone more zealous could hack that anyway. If you are concerned about that, then throw away all that stuff and simply use a HTTPS connection. With a trusted connection your sessions and access control rules are protected.
The better way is create API using SOAP or SAML2.
OAuth can be a very good solution: http://oauth.net/. It takes care of token and has a very secured API! If you wish to support secure authentication of web application + mobile application then it can be a good/proven solution!
On the other hand, it really depends on how complex your current system is and how the system is going to be in future.
I'm trying to create Drupal nodes using drupal_execute and it works fine.
The only issue is that I can't add the new node as another user than the signed in user.
Seems like $form_state['values']['name'] has no effect!
Is this even possible?
Any help will be greatly appreciated!
See https://drupal.org/node/178506#comment-726479 - although it mentions Drupal 5.7 at first, it applies to Drupal 6 too. The gist of it is, you have to (safely) impersonate another user. By doing that you get access to whatever function the user has access to.
Impersonating users is as simple as
global $user;
$original_user = $user;
$old_state = session_save_session();
session_save_session(FALSE);
$user = user_load(array('uid' => 1));
// Take your action here where you pretend to be the user with UID = 1 (typically the admin user on a site)
// If your code fails, it's not a problem because the session will not be saved
$user = $original_user;
session_save_session($old_state);
// From here on the $user is back to normal so it's OK for the session to be saved
Then the action you must take is to run drupal_execute() with the form array you have.
I've created an application using PHP and I'm going to sell it to my local market. I will personally be going to their locations to install/configure Apache & MySQL as well as installing my own code.
I would like a security system so that if anyone attempts to copy my code to an unauthorized machine, it won't run.
I know no one can prevent reverse engineering an application. even .exe (binary) files are cracked and with PHP (source code) anyone can do.
In my country those reverse engineers are really hard to find, so I would like to propose minimal security options like:
1) Create class (say, Navigation) which identifies system information like CPU ID, Computer name or any combination of hardware ID to make a UNIQUE_ID and matches with my given UNIQUE_ID (to the individual to whom I sold the application). If it's valid, it returns the navigation menu. Otherwise it will simply destroy the database and halt the execution by throwing an exception, maybe like:
class Navigation {
public function d() {
return current system UNIQUE_ID;
}
public function get() {
$a = file_get_contents('hash');
$c = $this->d();
if (crypt($c) != $a) {
//destory database
throw new Exception('');
} else {
return "<ul><li><a>home</a></li></ul>"; //navigation menu
}
}
}
2) Then during the installation process I'll change system UNIQUE_ID in "hash" file, create an object, and save it into a file (nav.obj):
(install.php)
<?php
$a=new Navigation;
$out=serialize($a);
file_put_contents('nav.obj', $out);
3) in header.php (which gets included in every file):
<?php
$menu=file_get_contents('nav.obj');
$menu=unserialize($a);
echo $menu->get();
?>
I know this method isn't full proof, but I'm pretty sure that around 60% of PHP developers won't be able to crack it!
Now I only need to get current system UNIQUE_ID.
I have created this function to get an unique ID based on hardware (Hard disk UUID). It is possible to use different resources like machine names, domains or even hard disk size to get a better approach depending on your needs.
function UniqueMachineID($salt = "") {
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
$temp = sys_get_temp_dir().DIRECTORY_SEPARATOR."diskpartscript.txt";
if(!file_exists($temp) && !is_file($temp)) file_put_contents($temp, "select disk 0\ndetail disk");
$output = shell_exec("diskpart /s ".$temp);
$lines = explode("\n",$output);
$result = array_filter($lines,function($line) {
return stripos($line,"ID:")!==false;
});
if(count($result)>0) {
$result = array_shift(array_values($result));
$result = explode(":",$result);
$result = trim(end($result));
} else $result = $output;
} else {
$result = shell_exec("blkid -o value -s UUID");
if(stripos($result,"blkid")!==false) {
$result = $_SERVER['HTTP_HOST'];
}
}
return md5($salt.md5($result));
}
echo UniqueMachineID();
As per http://man7.org/linux/man-pages/man5/machine-id.5.html
$machineId = trim(shell_exec('cat /etc/machine-id 2>/dev/null'));
EDIT for Tito:
[ekerner#**** ~]$ ls -l /etc/machine-id
-r--r--r--. 1 root root 33 Jul 8 2016 /etc/machine-id
EDIT 2 for Tito: Some things to consider and scenarios:
Is the user allowed to get a new machine? Id guess yes.
Or run on multiple devices?
Sounds like the machine could be irrelevant in your case?
If its user only (no machine restrictions) then Id go for a licencing service (relies on network).
There are many services for this:
Google Play (for Android apps) is a good example: https://developer.android.com/google/play/licensing/index.html
MS and Apple have similar services.
However just search the web for the term "Software Licensing Service" or "Cloud Based Software Licensing Service".
If its user + single device, then youll need to pass up the device id to whatever service you use or make, then allow the machine id to be updated, but not allow revert to previous machine id (would mean multiple devices).
However said services will give you the client code which should take care of that if its a requirement.
Two scenarios from experience:
1: User on any device: we simply made an API in the cloud (in a website) and a login screen in the app, when the user logged in it authenticated via the API and kept a token, and whenever the device was connected to the net the app would query the API and update the login and/or token.
You could alternatively have the login screen in the purchase (like maybe they already logged into a site to purchase), generate a key and pack it with or bind it into the app.
2: User plus machine:
Same thing except when the API is queried the machine id is passed up. The machine ID can change as many times as the user updates their device, but we kept a record of machine ids and made to ban rule on: if we saw an old (previously used) machine id then a certain amount of time had to have passed. Thus allowed the user to break their machine and pull out an old one.
Also to consider if you make one, how will you stop the app from working? Ppl are pretty clever it will need to be core compiled.
However that all being said, the various licensing services are pro at this and can cater for most needs. Plus in their experience theyve already overcome the security pitfalls. Id name one that I like except its yours to search out.
Nice if you can come on back with and positive or negative outcomes from your trails.
function getMachineId() {
$fingerprint = [php_uname(), disk_total_space('.'), filectime('/'), phpversion()];
return hash('sha256', json_encode($fingerprint));
}
This will get a probably-unique id based on a hash of:
The server's OS, OS version, hostname, and architecture.
The total space (not free space) on the drive where the php script is.
The Unix timestamp creation time of the computer's root file system.
The currently installed PHP version.
Unlike the other answers it doesn't depend on shell_exec() being enabled.