I need to create a system plugin (no auth plugin!) where a user which logges into the frontend automaticaly gets logged in the backend too.
(The user has the rights to log into the backend via /administrator.)
I try to do it via the very basic code you see below, the result is positive, but if i go to the backend the user still needs to log in.
In the session table the backend session row is set, but the "guest" field is set to 1 instead of 0 and the userid is set to 0 instead of the correct id.
How can this be done?
function onAfterInitialise() {
if(JFactory::getUser()->get('id')) { // logged in?
$credentials = array();
$credentials['username'] = "walter"; // hardcoded first
$credentials['password'] = "123"; // hardcoded first
$options = array();
$options['action'] = 'core.login.admin';
$result = $app->login($credentials, $options); // this seams to work
if (!($result instanceof Exception)) {
$app->redirect("www.bummer.de");
}
}
Apart from this being a very bad idea, as mentioned in this question Joomla! is implemented as two applications a front-end (/index.php) and back-end application (/administrator/index.php).
In the code provided you don't show where $app is initialised so I'm guessing that it's probably something like $app->JFactory::getApplication('site');.
To login to the admin app you need to get it rather than the front-end client app e.g.
$adminApp->JFactory::getApplication('administrator');
$result = $adminApp->login($credentials, $options);
n.b. this is untested code just typed in to stack overflow... it should be right.
Related
As the title, I ask this question because the only way I know how to check if a user is logged in, is by having on top of each file a session and a query to data base to compared the sessions value.
I have something like this function, then I call this function on top of every php file, this works fine. However I dont think big website such as facebook, youtube and so on has this approach, also this means that all my files have to be .php I cant have .html as I wouldn't be able to run the function below.
public function isSessionValid()
{
session_start();
$dbConfig = new dbconfig("users");
$dbUser = $dbConfig->getDbUser();
$getUser = new GetUser($dbUser);
$result = $getUser->getUser($_SESSION['UN'],$_SESSION['PW'] );
if(!count($result) > 0){
header("Location: ../index.html");
}
}
My question is what are other efficient ways of checking for users credentials?
You don't want to have something like:
$_SESSION['PW']
Plain text unencrypted passwords are a serious concern. You could do something where upon login, you create a access token that is a random hashed string and that gets saved to the users cookies.
Here's an example:
function login()
{
$userName = 'billy';
$password = 'foobar';
// get your user data using username and password.
$userObject = new User();
$userId = $userObject->id;
// create our secure hash.
$accessToken = password_hash($password, PASSWORD_DEFAULT);
// update the user in the row.
mysqli_query($link, "UPDATE users set access_token='$accessToken' WHERE id = $userId");
// expires in 1 day, auto logout.
setcookie('userAccessToken', $accessToken, time() + 86400);
}
function getUser() {
return mysqli_query($link, "SELECT * from users WHERE access_token = ".$_COOKIE['userAccessToken']);
}
Now you only need to check for one attribute which is the access token, and its stored in the cookies in case they come back. Using the hash approach prevents anyone sniffing the cookies and getting private information.
For code maintainability you don't want duplicate code and should always try to create small reusable components that can be used across all your pages. Make a PHP file called auth.php and then just require it in the pages where you need it.
// UserPage.php
require_once __DIR__.'/lib/auth.php';
$user = getUser();
// MessagePage.php
require_once __DIR__.'/lib/auth.php';
$user = getUser();
// lib/auth.php
function getUser() {
return mysqli_query($link, "SELECT * from users WHERE access_token = ".$_COOKIE['userAccessToken']);
}
As a side note, rather than writing your application in plain php and building your own framework, I recommend you checkout laravel.com. They have video tutorials and the framework solves a lot of common problems developers run into, including this one.
One solution would be to configure the webserver to automatically route all requests through isSessionValid() first, then to their actual destination.
if someone can help with zend returning data from wrong user
Our current problem is when multiple users use our zend application it frequently returning data from other users to another curently loged user,. ie it is mixing users data. We have tried reinstaling the PC, changing browsers, disabling caching..., nothing helped.
Any help apreciated
In zend 2 you can use container, and whenever user has logged in and you want track his session you can do this as following:
$loggedUser = new Container('user');
$loggedUser->loggedIn = true;
var_dump($loggedUser->loggedIn); //will print true
In case you want to track guest session, simply you can use new different Container for it
$guest = new Container('guest');
$guest->visited = true;
var_dump($guest->visited); //will print true
also you can use offsetGet, offsetSet instead of setting variables directly
$guest = new Container('guest');
$guest->offesetSet('visited') = true;
var_dump($guest->offsetGet('visited'));
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 am new to Magento Web-Service and have to expand it.
The Webservice shell be able to login an customer, give me the session cookie back so that I can redirect to a file that sets the cookie again, redirects me and I can see my cart and proceed to checkout on the Magento Store.
The Problem:
Magento creates a cookie (that contains the session id or whatever, ive tried to set this cookie manual and them im logged in) instead of setting a session when the customer logs in.
I've tried now for several hours to get this cookie that is set by magento in my magento web-service. It seems the cookie isn't set when i call
$session = Mage::getSingleton('customer/session');
return $session->getCookie()->get('frontend');
Heres my complete Code:
Magento Webservice Api:
<?php
class Customapi_Model_Core_Api
{
public function __construct()
{
}
public function checkout($user, $cart)
{
$ret['cookie'] = $this->login($user);
//$coreCookie = Mage::getSingleton('core/cookie');
//$ret['cookie'] = $_COOKIE['frontend'];
return $ret;
}
function login($user)
{
Mage::getSingleton('core/session', array('name'=>'frontend'));
$session = Mage::getSingleton('customer/session');
try
{
$session->loginById($user['id']);
}
catch (Exception $e)
{
}
return $session->getCookie()->get('frontend');
}
}
?>
Heres my Api Call in Php:
<?php
$teambook_path = 'http://localhost/magento/';
$soap = new SoapClient('http://localhost/magento/api/?wsdl');
$soap->startSession();
$sessionId = $soap->login('ApiUser', 'ApiKey');
$userSession = $soap->call(
$sessionId,
'customapi.checkout',
array(
array(
'id' => 1,
'username' => 'Ruf_Michael#gmx.de',
'password' => '***'
),
array(
)
)
);
echo '<pre>';
var_dump($userSession)."\n";
if(isset($userSession['sid']))
echo ''.$userSession['sid'].''."\n";
echo '</pre>';
$soap->endSession($sessionId);
?>
Thanks for every help!
MRu
Sorry i am writing an answer but the comment box denied me to write more than ... letters.
I've tried both codes you posted and all I get is an empty Array or Bool false.
I wrote a static function:
private static $cookie = array();
public static function cookie($key, $value)
{
if($key == 'frontend') {
self::$cookie['key'] = $key;
self::$cookie['value'] = $value;
}
}
that is called in Mage_Core_Model_Session_Abstract_Varien::start and I got the frontend cookie value:
Customapi_Model_Core_Api::cookie($sessionName, $this->getSessionId());
in line 125.
But that didnt solve my basic Problem:
The Session created in the Api call can't be restored, although it is set to the correct value.
Thanks for your help!
You can get an array of all your cookies with the following command:
Mage::getModel('core/cookie')->get();
The frontend cookie can be retrieved like this:
Mage::getModel('core/cookie')->get('frontend');
From your commented code I can see that you already knew that.
As far as I know, when you log in a user, Magento doesn't just create a new session id, it uses the session id of the active connection (which is generated by PHP itself). You are logging in the user and associating him to the session that your API client just created with Magento. Thus, the code that you have commented seems to be correct for what you are trying to achieve.
Now you should just need to get the returned session id and use it in your new request as the 'frontend' cookie.
Edit (a second time)
Magento has different sessions inside a single PHP session which it uses for different scopes. For instance, there is the core scope, the customer scope, etc. However, the customer scope is also specific to a given website. So, you can have a customer_website_one and a customer_website_two scope.
If you want to log in your user, you have to tell Magento in which website that is. Take the following code as an example
// This code goes inside your Magento API class method
// These two lines get your website code for the website with id 1
// You can obviously simply hardcode the $code variable if you prefer
// It must obviously be the website code to which your users will be redirected in the end
$webSites = Mage::app()->getWebsites();
$code = $webSites[1]->getCode();
$session = Mage::getSingleton("customer/session"); // This initiates the PHP session
// The following line is the trick here. You simulate that you
// entered Magento through a website (instead of the API) so if you log in your user
// his info will be stored in the customer_your_website scope
$session->init('customer_' . $code);
$session->loginById(4); // Just logging in some example user
return session_id(); // this holds your session id
If I understand you correctly, you now want to let the user open a PHP script in your server that sets the Magento Cookie to what you just returned in your API method. I wrote the following example which you would access like this: example.com/set_cookie.php?session=THE_RETURNED_SESSION_ID
<?php
// Make sure you match the cookie path magento is setting
setcookie('frontend', $_GET['session'], 0, '/your/magento/cookie/path');
header('Location: http://example.com');
?>
That should do it. Your user is now logged in (at least I got it to work in my test environment). One thing you should keep in mind is that Magento has a Session Validation Mechanism which will fail if enabled. That's because your session stores info about which browser you are using, the IP from which you are connecting, etc. These data will not match between calls through the API methods and the browser later. Here is an example output of the command print_r($session->getData()) after setting the session in the API method
[_session_validator_data] => Array
(
[remote_addr] => 172.20.1.1
[http_via] =>
[http_x_forwarded_for] =>
[http_user_agent] => PHP-SOAP/5.3.5
)
Make sure you turn of the validation in the Magento Admin in Settings > Configuration > General > Web > Session Validation Settings
I have a problem with the following implementation of hook_cron in Drupal 6.1.3.
The script below runs exactly as expected: it sends a welcome letter to new members, and updates a hidden field in their profile to designate that the letter has been sent. There are no errors in the letter, all new members are accounted for, etc.
The problem is that the last line -- updating the profile -- doesn't seem to work when Drupal cron is invoked by the 'real' cron on the server.
When I run cron manually (such as via /admin/reports/status/run-cron) the profile fields get updated as expected.
Any suggestions as to what might be causing this?
(Note, since someone will suggest it: members join by means outside of Drupal, and are uploaded to Drupal nightly, so Drupal's built-in welcome letters won't work (I think).)
<?php
function foo_cron() {
// Find users who have not received the new member letter,
// and send them a welcome email
// Get users who have not recd a message, as per the profile value setting
$pending_count_sql = "SELECT COUNT(*) FROM {profile_values} v
WHERE (v.value = 0) AND (v.fid = 7)"; //fid 7 is the profile field for profile_intro_email_sent
if (db_result(db_query($pending_count_sql))) {
// Load the message template, since we
// know we have users to feed into it.
$email_template_file = "/home/foo/public_html/drupal/" .
drupal_get_path('module', 'foo') .
"/emails/foo-new-member-email-template.txt";
$email_template_data = file_get_contents($email_template_file);
fclose($email_template_fh);
//We'll just pull the uid, since we have to run user_load anyway
$query = "SELECT v.uid FROM {profile_values} v
WHERE (v.value = 0) AND (v.fid = 7)";
$result = db_query(($query));
// Loop through the uids, loading profiles so as to access string replacement variables
while ($item = db_fetch_object($result)) {
$new_member = user_load($item->uid);
$translation_key = array(
// ... code that generates the string replacement array ...
);
// Compose the email component of the message, and send to user
$email_text = t($email_template_data, $translation_key);
$language = user_preferred_language($new_member); // use member's language preference
$params['subject'] = 'New Member Benefits - Welcome to FOO!';
$params['content-type'] = 'text/plain; charset=UTF-8; format=flowed;';
$params['content'] = $email_text;
drupal_mail('foo', 'welcome_letter', $new_member->mail, $language, $params, 'webmaster#foo.org');
// Mark the user's profile to indicate that the message was sent
$change = array(
// Rebuild all of the profile fields in this category,
// since they'll be deleted otherwise
'profile_first_name' => $new_member->profile_first_name,
'profile_last_name' => $new_member->profile_last_name,
'profile_intro_email_sent' => 1);
profile_save_profile($change, $new_member, "Membership Data");
}
}
}
To safely switch users
http://api.drupal.org/api/function/session_save_session/6
<?php
global $user;
$original_user = $user;
session_save_session(FALSE); // D7: use drupal_save_session(FALSE);
$user = user_load(array('uid' => 1)); // D7: use user_load(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(TRUE); // // D7: use drupal_save_session(TRUE);
// From here on the $user is back to normal so it's OK for the session to be saved
?>
Taken from here:
drupal dot org/node/218104
yes i confirm drupal cron user profile is "anonymous" so you have to add the permission de manager user for the "anonymous" user which is not very good in term of security ..
Not quite a random guess ... but close ...
When "real" cron runs code, it runs it as a particular user.
Similarly, when you run the Drupal cron code manually, the code will also be running as a particular user.
My suspicion is that the two users are different, with different permissions, and that's causing the failure.
Does the cron job's user have access to write the database, or read only?
Are there any log files generated by the cron job?
Update: By 'user' above, I'm referring to the user accounts on the host server, not Drupal accounts. For example, on a sandbox system I use for testing Drupal changes, Apache runs under the noone account.
profile_save_profile dosn't check for permissions or as far as I can see do 'global $user' so I don't know if this is the real issue.
$new_member = user_load($item->uid);
This looks wrong user_load should take an array not a uid (unless you are using Drupal7), but if that didn't work the rest of the code would fail too.