I am using Codeigniter with the TankAuth library installed and trying to upload to index.php/requests/doUpload from swfupload but can't access the page as authenticated. I have read many posts around the net about similar problem and tried to set $config['sess_match_useragent'] = FALSE; but still no difference. I have ended up skipping the login check in my controller for testing purposes. But now I need to access tankAuth library from my controller to get the current logged in user ID. It is requested in my application and cannot skip it, I really need to pass the logged in user id to that doUpload model. I have setup controller like this:
function doUploadFileFn() {
if (!$this->tank_auth->is_logged_in()) {
return;
} else {
$user_id = $this->tank_auth->get_user_id();
$this->load->model('requests/doUploadFile');
$this->doUploadFile->uploadData($user_id);
}
}
Now, it does not pass the is_logged_in() check, as I learned from other posts, CI deletes the session but I have setup the config not to match the user agent but still not working.
Is there any solution to this out there ?
Following the tutorial in the CI forums I was able to achieve what you are asking for.
1) Put this in the SWFUpload JS config:
post_params: {"<?php echo $this->config->item('sess_cookie_name'); ?>" :"<?php echo $this->session->get_cookie_data(); ?>"},
2) And place the MY_Session.php file in your application/libraries/ folder.
3) The new library should be loaded the moment the view is loaded if not (for some reason) then load your library in the controller.
P.S: You need to set:
$config['sess_match_useragent'] = FALSE;
Otherwise a new session will be created for a useragent Shockwave Flash
EDIT: Okay, based on your comment..you really need to set your post_params setting to your current session so it can be sent when the flash post to your controller, now in your case the best thing I could think of is the below:
Your externalUntouchableJsFile.js:
// JS scripts...
...
var swfu = new SWFUpload({
...
...
post_params: GLOBAL_VAR,
...
});
...
// rest of your JS
And in your PHP view and before loading this JS file have something like:
<script>
var GLOBAL_VAR = {};
<?php if(session_is_there) { ?>
GLOBAL_VAR = {"<?php echo $this->config->item('sess_cookie_name'); ?>" :"<?php echo $this->session->get_cookie_data(); ?>"}
<?php } ?>
</script>
<script type="text/javascript" src="<?php echo base_url() ?>path/to/js/externalUntouchableJsFile.js"></script>
EDIT 2: Since you are using an external js file, you may forget to define the global variable so use:
post_params: (typeof GLOBAL_VAR === 'undefined') ? {}:GLOBAL_VAR,
It bears mentioning that the Flash file should be served from the same domain as your CI site or one won't be able to read the other's cookies. Also make sure that the login cookie path is set to the root path. If SWFUpload can not read the login cookie, it can not send it either.
Flash has limited access to session cookies, as documented here in the SWFUpload forum. Is it possible that you've set the auto login to avoid setting an expiration (in config/tank_auth.php), thereby making it a session cookie? If that is the case, then the SWFUpload SWF may not be able to access or send the autologin cookie value, depending on the version of Flash player on the computer. Double-check your cookie expiration values using a debug tool like Firebug to see if this is the case. If the upload works when you check a "remember" me box but not otherwise, that would indicate a session cookie problem.
To force the SWF to pass the TankAuth cookie value on file uploads, you could first overload the cookie helper get_cookie function to look in either the $_COOKIE array or the $_POST array for values. Then, it appears that with SWFUpload v2 you can send additional POST values along with the upload, and this would be the way to send the autologin key, which would then allow your controller to get the user_id. But before hacking the Cookie helper, make sure your moving parts are working first, as described in the first paragraph.
I have managed to apply a rough fix for this by passing the logged user ID in the URL, and getting it from Javascript with URL functions. It's the best method I can rely to right now, it doesn't bother me too much that the user ID is visible because I'm using a managed iframe to display that specific part of the app and the app is for internal company use only.
Thanks for your answers.
Related
I have been using Code Igniter for quite a while, and I understand that "Session/flash data only works after a redirect/page reload". An interesting thing I find out on my local host is that I can manage to get flash data with out reloading/redirect the page. Can any one explain to me how is this managed to work? I was hoping that I cant get any messages.
In Controller:
$this->session->set_flashdata("success", "worked");
$this->load->view('layouts/main');
In Main View:
<p class = 'bg-success'>
<?php if($this ->session->flashdata('success')): ?>
<?php echo $this ->session->flashdata('success');?>
<?php endif; ?>
</p>
After this is being executed, I can view the flash data worked. How did it work? Isn't CI flash data is only going to be appear on the next user request?(i.e. a redirect/page reload?). I just loaded a view after setting the flash data, theoretically, it should not work, and no message should appear, as this is only the first request.
CodeIgniter supports flashdata, or session data that will only be available for the next request, and is then automatically cleared.This can be very useful, especially for one-time informational, error or status messages.
For more see Codeigniter Session
If you want to display session data without redirect page then you should use $this->session->userdata() in codeigniter
Controller code
$this->session->set_userdata('msg', "Done successfully..");
To mark an existing item as “flashdata”:
$this->session->mark_as_flash('msg');
Condition in view to display msg
if(isset($this->session->userdata('msg')) echo $this->session->userdata('msg') ;
Or you may use Tempdata
CodeIgniter also supports “tempdata”, or session data with a specific expiration time. After the value expires, or the session expires or is deleted, the value is automatically removed.
Similarly to flashdata, tempdata variables are regular session vars that are marked in a specific way under the ‘__ci_vars’ key (again, don’t touch that one).
To mark an existing item as “tempdata”, simply pass its key and expiry time (in seconds!) to the mark_as_temp() method:
// 'item' will be erased after 300 seconds
$this->session->mark_as_temp('msg', 300);
I am making AJAX like function but I have problem that bad user can change the value into any other current user. So, how can I prevent this thing?
$live = 'user1';
$fol = 'user2';
function ajax(like){
var data = 'like='+like+'&CURRENTUSER=<?php echo $live; ?>&TOFOLLOW=<?php echo $fol; ?>';
$.ajax( {
type: 'POST',
url: 'ajax.php',
data: data,
success: function(e) {
$('#success').html(e);
}
});
}
Also I want to move this ajax function into ajax.js file, but i am have problem in getting the value $live and $fol of users because echo $live doesn't work on .js.
So, is there any way to do this like Facebook, Twitter AJAX function does ?
This solution works for apache web-server. For interpreting JS file using php, add this line to your .htaccess file:
AddType application/x-httpd-php .js
And put your script inside ajax.js. One other way is using rewrite URL:
RewriteEngine On
RewriteRule ^ajax.js$ ajax.js.php [L]
And put your scripts inside ajax.js.php file. Of course, all these are if you want to show your URL as JS file.
at the top of your ajax.js or ajax.js.php file, before any kind of output, put this:
header('Content-Type: application/javascript');
I have problem that bad user can change the value into any other current user. So, how can I prevent this thing?
Of course you can not do that at all.
HTTP is a stateless protocol – so each and every request that reaches your server is to be mistrusted, period.
You have to check server-side whether the requesting client is authorized to request/perform whatever action it is he wants to trigger – f.e. by checking that the user id that is passed as the “current” user against the session where you stored your login information. (So when you have the id of the current user stored in there, then there’s no need to actually send it from the client any more in the first place.)
This is one of the most basic security principles of any web application – don’t trust any incoming request, until you have verified that the client has the appropriate authorization. So asking for how to “hide” any data that is send from the client is completely the wrong question – that would be what’s called “security by obscurity”, and that does not work.
There can be many solutions for such problem.
Add one of follow user in session before page load so even you dont need to send data in ajax. Just need to confirm action and all data will be taken from session. Hence hackers cant modify users.(This is how i solved the problem in my project)
You can build an function like encode() & decode(). when you are using data in file encode() it first.Then at code end use decode() to extract the info. Since if invalid data came out mean some one has tempered and you will not execute that action. But you have to create such encode() & decode() yourself.
$live = encode(user1);
At php end
$real_live = decode($live);
3. Ajax request to when start php execution you can have a function like
check_auth(user1,user2);
So even if some one used bad data your security rules can filter them.
Hope you can use any of them.
I have several pages inside an AJAX directory. I don't want these pages accessible directly so you cannot just type in the URL of the page within the AJAX directory and access it. I "solved" this by using a PHP session on the page that calls it as follows:
Main page:
<?php
session_start();
$_SESSION['download']='ok';
?>
and on the ajax page I have this:
<?php
session_start();
if($_SESSION['download']!=='ok'){
$redirect='/index.php'; //URL of the page where you want to redirect.
header("Location: $redirect");
exit;}
?>
The only problem is that if a user goes through the correct process once, the cookie is stored and they can now access the page directly. How do I kill the session once they leave the parent page?
thx
why use session ?
if i understood what you want:
<?php /// Is ajax request var ?
if (isset($_SERVER['HTTP_X_REQUESTED_WITH'])) {
if (strtolower($_SERVER['HTTP_X_REQUESTED_WITH'])=="xmlhttprequest") {
// do your ajax code
} else {
// redirect user to index.php since we do not allow direct script access, unless its ajax called
$redirect='/index.php'; //URL of the page where you want to redirect.
header("Location: $redirect");
exit();
}
} ?>
A really simple solution is to open up each of the files you want to protect from direct URL entry & add the following to the top:
<?php if (isset($_GET['ajax']) != true) die();?>
Now get rid of your redirect script since it's useless now. You don't need to use sessions for this. Every time you request a page, use it's direct URL, just add ?ajax=1 to the end of it.
By adding the ?ajax=1, PHP will set a key of 'ajax' to the $_GET global variable with the value of 1. If ?ajax=1 is omitted from the URL then PHP will not set a key of 'ajax' in $_GET and thus when you check if it's set with isset() it will return false, thus the script will die and not output anything. Essentially the page will only output data if ?ajax=1 is at the end of the URL.
Someone could still "spoof" the URL and add '?ajax=1' themselves, but that is not the default behavior for people or web browsers. If you absolutely need to prevent this then it will be much more complicated, e.g. using templates outside of a publicly available folder. Most other "simple" solutions will have the same "spoofing" potential.
There's really no way to accomplish this with a 100% certainty - the problem is, both AJAX and regular web browser calls to your web site are using the same underlying protocol: HTTP. If the integrity and security of your site depends on keeping HTTP clients from requesting a specific URL then your design is wrong.
so how do you prevent people from directly accessing files inside certain directories while still letting the site use them??
Create a controller file. Send all AJAX requests to this controller.
ajax-control.php
<?php
$is_ajax = true;
include "ajaxincludes/test.php";
// ... use the ajax classes/functions ...
ajaxincludes/test.php
<?php
if (!isset($is_ajax) || !$is_ajax)) {
exit("Hey you're not AJAX!");
}
// ... continue with internal ajax logic ...
If clients try to access the file directly at http://mysite/ajaxincludes/test.php they'll get the error message. Accessing http://mysite/ajax-control.php will include the desired file.
I don't think there is a surefire way to do what you are asking, since HTTP request headers can be faked. However, you can use $_SERVER['HTTP_REFERER'] to see if the request appears to be coming from another page on your site.
If the rest of the security on your site is good, the failure of this method would not grant the user access to anything they were not already able to access.
I've never tried this but maybe you could do something with jQuery's .unload() and then call a PHP page to unset() the session.
Why not (on Ajax page):
session_start();
if($_SESSION['download']!=='ok'){
$redirect='/index.php'; //URL of the page where you want to redirect.
header("Location: $redirect");
exit;
}
// do whatever you want with "access granted" user
// remove the download flag for this session
unset($_SESSION["download"]);
First of all, I'm using KohanaPHP Framework.
I've impletemented SWFUpload successfully, working quite nice. I'm having only one issue.
The main problem is I need to allow users to upload attachments before submitting form. So I decided to use Session var to store attachments array. Unfortunately, it is working inly if I use HTML upload (based on iframe), but not when I use SWFUpload.
I tried to Google for that, but without any working solution. Any ideas?
Update & Solution
Basically, I didn't know there's an issue with Flash and sessions. Providing the same session id didn't helped me because I got unlogged. Anyway I got a solution for people with the same issue.
I created an unique ID of an item. I upload files to temporary directory, then... I'm scanning this directory and I'm adding uploaded filenames to session.
Tom
What you need to is pass the session id to SWFUpload by hand. In a nutshell, you do this in your template:
<script type="text/javascript">
var PHPSESSID = <?php echo json_encode(session_id()); ?>;
</script>
Then you do this with your SWFUpload code:
var settings = {
post_params: {"PHPSESSID" : PHPSESSID},
/* the rest of the settings */
};
And finally, in your application code, before you call session_start, you need to do this (usually just in your index.php or whatever bootstrap you use):
// Restore session that came from SWFUpload
if(isset($_REQUEST['PHPSESSID']))
session_id($_REQUEST['PHPSESSID']);
After this session_start() will use the correct session even for SWFUpload requests.
Just want to know if anyone have the same problem.
The website need to login to perform certain task. We use stock Auth component to do the job.
Everything is fine until it hits an interface which build in Flash. Talking to Amf seems fine. But when the Flash player try to talk to other controller - got redirect because the session in not presented.
So basically when a user login - I need to somehow find a way to login the Flash player in as well.
ADDITION:
This only solve half of the problem.
Backtrack a little bit. How the Auth components evaluate the requester?
If the Session.checkAgent is true. They check if its the last one. So Flash has no chance they have a different Agent string.
OK now - Auth check them out - what? The Session cookie they store earlier ... so fail again.
UPDATE
Thanks for all the answers.
I have tried the suggested solution. Only one problem.
I am using Amf (as Cakephp Plugins) when I tried to test if the $this->params['actions'] is start with amf - it works sometime doesn't work sometime. Looking at "Charles" I can see they all call to the amf controller. Very puzzling ....
in config/core.php
try
Configure::write('Session.checkAgent', false);
It appears that if you manage to call your Session->id($sessionId) before any call to Session->read(), Session->check() or Session->write(), you don't need to bother with all the destroy old session, update userAgent and delete cookie stuff.
use this in beforeFilter action of your controllere called by flash:
if ($this->action == 'flashCalledAction') {
Configure::write('Security.level', 'medium');
//Using instead the session specified
$this->Session->destroy();
$this->Session->id($_REQUEST['sessionId']);
$this->Session->start();
// We revert to the original userAgent because starting a new session modified it
$this->Session->write('Config.userAgent', $_REQUEST['userAgent']);
// We delete the flash cookie, forcing it to restart this whole process on each request
setcookie(Configure::read('Session.cookie'), '', time() - 42000, $this->Session->path);
}
then you have to pass these 2 params in each flash call to this controller:
param: 'userAgent' -> value: '$this->Session->read('Config.userAgent')'
param: 'sessionId' -> value: $this->Session->id()
http://blogs.bigfish.tv/adam/2008/04/01/cakephp-12-sessions-and-swfupload/
This is specifically for swfUpload but the process of appending the session_id to the urls and the settings for checkAgent and session security are covered and should help point you in the right direction.
Flash doesn't send the cookie along with its requests, that's why Cake doesn't log it in. The way I do it is: you need to somehow pass $this->Session->id() along with your flash requests. That is probably the hardest part because some flash application doesn't let you tag some info along in the request. Then write a component (FlashComponent, or whatever you want to call it) that check if it's a flash request, then look for the session id in its request and set the session id. You need to include this component before 'Auth': so var $components = array('Flash','Auth',...) to intercept the request before Auth does.
Or you can set Auth->allow list, but then you will expose these actions to non-authorization, and the action won't know who the current logged in user is (unless you can pass something in the flash request, in that case, use my first solution).