I want the Security Component turned on.
BUT when you load a CakePHP app inside a Facebook tab, FB posts $_REQUEST['signed_request'] to my form - the problem with this is that the Security Component "reacts" to this "post" and gives me validation errors, black-hole, etc.
How do I go around this?
I could not find anything on the documentation to go around this problem.
What I wanted was to somehow run the Security Component "manually" so that it only "reacts" when I actually submit my form and not when Facebook posts the $_REQUEST['signed_request'] to my form.
UPDATE:
<?php
App::uses('CakeEmail', 'Network/Email');
class PagesController extends AppController {
public $helpers = array('Html','Form');
public $components = array('RequestHandler');
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('*');
$this->Security->validatePost = true;
$this->Security->csrfCheck = true;
$this->Security->unlockedFields[] = 'signed_request';
}
public function home() {
$this->loadModel('Memberx');
if($this->request->is('post') && isset($this->request->data['Memberx']['name'])) {
//...save here, etc. ...
}
}
FYI: I get a "black hole" error.
FINAL UPDATE (After #tigrang's answer):
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('*');
$this->set('hasLiked', false);
if(isset($this->request->data['signed_request'])){
$this->set('hasLiked', $this->hasLiked($this->request->data['signed_request']));
}
if(isset($this->request->data['Memberx']['signed_request'])) {
$this->set('hasLiked', $this->hasLiked($this->request->data['Memberx']['signed_request']));
}
/*
To go around Facebook's post $_REQUEST['signed_request'],
we unset the $_REQUEST['signed_request'] and disable the csrfCheck
ONLY after we have set the hasLiked view variable
*/
unset($this->request->data['signed_request']);
if (empty($this->request->data)) {
$this->Security->csrfCheck = false;
}
}
Then, I do something like below in my views:
<?php
if($hasLiked) {
?>
You have liked this page!
<?php
}
?>
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('*');
$this->_validateFbRequest();
}
protected function _valdiateFbRequest() {
if (!isset($this->request->data['signed_request'])) {
// not a valid request from fb
// throw exception or handle however you want
return;
}
$signedRequest = $this->request->data['signed_request'];
unset($this->request->data['signed_request']);
if (empty($this->request->data)) {
$this->Security->csrfCheck = false;
}
// validate the request
}
Related
im tryiing to create a login system with cide igniter
here is my controller
<?php
class LoginController extends CI_Controller {
public function index()
{
$this->load->view('login');
}
public function checkLogin()
{
$this->form_validation->set_rules('login','Login','required');
$this->form_validation->set_rules('password','Password','required|callback_Verification');
if($this->form_validation->run() ==false)
{
$this->load->view('login');
}
else
{
redirect('HomeController/index');
}
}
public function Verification()
{
$login = $this->input->post('login');
$password = $this->input->post('password');
$this->load->model('LoginModel');
if($this->LoginModel->Login('$login','$password'))
{
return true;
}
else
{
$this->form_validation->set_message('Verification','Mot de passe ou login incorrect');
return false;
}
}
}
?>
here is the model
<?php
class LoginModel extends CI_Model {
public function Login($login, $password)
{
$this->db->select('login','password');
$this->db->from('users');
$this->db->where('login',$login);
$this->db->where('password',$password);
$query = $this->db->get();
if($query->num_rows()==1){
return true;
}else{
return false;
}
}
}
?>
why isnt it workin it gives me the set message (login incorrect wether i enter a correct login or not I cant find the problem
It is probably the issue with Codeigniter 3.0 version, there is a problem with their session handling class.
For now i would suggest using the Codeiginter 2.x version, since the 3.0 versions are still ongoing development.
I ran into this problem earlier and it took days for me to figure out that problem.
To stay basic I would like to create a bookmark app
I have a simple bookmarklet
javascript:location.href='http://zas.dev/add?url='+encodeURIComponent(location.href)
I created a rest controller
<?php
use zas\Repositories\DbLinkRepository;
class LinksController extends BaseController {
protected $link;
function __construct(DbLinkRepository $link) {
$this->link=$link;
// ...
//$this->beforeFilter('auth.basic', array('except' => array('index', 'show', 'store')));
// ...
}
public function index()
{
//return Redirect::to('home');
}
public function create()
{
}
public function store()
{
return 'hello';
//$this->link->addLink(Input::get('url'));
//return Redirect::to(Input::get('url'));
}
public function show($id)
{
//$url = $this->link->getUrl($id);
//return Redirect::to($url);
}
public function edit($id)
{
}
public function update($id){
}
public function destroy($id){
}
}
in the routes.php, I created a ressource
Route::resource('links','LinksController');
and as I want to redirect /add to the store method I added
Route::get('/add',function(){
return Redirect::action('LinksController#store');
});
but it never display the hello message, in place it redirects me to
http://zas.dev/links
I also tried with
return Redirect::route('links.store');
without much success
thanks for your help
Ok I now get what you are trying to do. This will work:
Route::get('add', 'LinksController#store');
Remove:
Route::resource('links','LinksController');
and remove:
Route::get('/add',function(){
return Redirect::action('LinksController#store');
});
Sorry it took so long!
The problem is that once you Redirect::, you loose all the Input values, so you should manually give them to your controller when you do the redirect, like so :
Redirect::route('links.store', ["url" => Input::get("url")]);
Finally add an $url parameter to your store method to receive the value we give it in the previous method, like this :
public function store($url) {
$this->link->addLink($url);
return Redirect::to($url);
}
How can i show or hide login/logout link if user is loged in. Should this be done directly in view?
In my onDispatch i see that it is using $this->getAdminAuthService()->hasIdentity() to check if user is loged in.
How to use it in view like this?
if($this->getAdminAuthService()->hasIdentity()){
echo "login";
}
else {
echo "Logout"
}
Try this in your controller:
public function onDispatch(\Zend\Mvc\MvcEvent $e)
{
$header = new ViewModel(array('login'=>$this->getAdminAuthService()->hasIdentity()));
$header->setTemplate('layout/header');
$this->layout()->addChild($header, 'header');
}
then :
//layout/header.phtml
if($this->login){
echo "login";
} else {
echo "Logout"
}
A view helper might be a more self contained solution for this
namespace MyModule\View\Helper;
use Zend\View\Helper\AbstractHelper;
use MyModule\Service\AuthService;
class IsAuthenticated extends AbstractHelper
{
protected $authService;
public function __construct(AuthService $authService) {
$this->authService = $authService;
}
public function __invoke()
{
return $this->authService->hasIdentity();
}
}
Create a factory in your module.php
public function getViewHelperConfig()
{
return array(
'factories' => array(
'IsAuthenticated' => factory($sl) {
$authService = $sl->getServiceLocator()->get('AuthService');
return new View\Helper\IsAuthenticated($authService);
},
),
);
}
Then you can use this within the view or layout - perhaps with a view partial
if ($this->isAuthenticated()) {
// render the login/logout
$this->partial('some/view/file', array('foo', 'bar'));
}
The plugin could be expanded to proxy to other AuthService methods. However I hope this brief example shows how to go about it.
I don't know what version of ZF2 you're using, but 2.2.x ships with a view helper for checking a user's identity from the AuthenticationService out of the box.
$this->identity();
View Helper - Identity
I am learning Zend Framework and having issues with Zend_Session_Namespace.
Here is the scenario:
Homepage(user clicks on login-Index Controller)
login page(user auth is done->Login Controller)
On Successful login: Create a new zend_Session_Namespace("login") and take him to another page with home page button.
User Clicks the Home Page Button.I can Access the username from the session and display the welcome message.
User again clicks on the login page. I am checking isset($session->name) to prevent login again and take him to other page instead. --> I am failing here . The session is somehow reset , I am quite unsure what I am missing.
class IndexController extends Zend_Controller_Action
{
public function init()
{
}
public function indexAction()
{
$session = new Zend_Session_Namespace("login_session");
//Check if the session is already valid
if(isset($session->name)) {
$this->view->userLoggedIn="true";
$this->view->name=$session->name;
}
}
}
class LoginController extends Zend_Controller_Action
{
public function loginaction(){
$session = new Zend_Session_Namespace("login_session");
if(isset($session->name)){
//Redirect to New Page-Already Logged In
} else {
//Authenticate the user and if login is successful
$session->name="USER_NAME";
}
}
}
Thank You.
This code looks ok except for the previously mentioned typo.
It's possible and likely that somewhere else in your code you inadvertently overwrite the session namespace. I think we've all done that at least once.
I would suggest that instead of trying to roll your own authentication solution, use the one that ZF provides: Zend_Auth
a basic Zend_Auth login/logout might look like:
//non production code for example only
public function loginAction()
{
$form = new Application_Form_Login();
if ($this->getRequest()->isPost()) {
if ($form->isValid($this->getRequest()->getPost())) {
$data = $form->getValues();
$authAdapter = new My_Auth_Adapter($data['username'], $data['password']);
//authenticate
$result = $authAdapter->authenticate();
if ($result->isValid()) {
//store the user object
$auth = Zend_Auth::getInstance();
//access Zend_Auth session namespace
$storage = $auth->getStorage();
$storage->write($authAdapter->getUser());
//add message to flashmessenger
$this->message->addMessage('Welcome');
//redirect to the homepage
return $this->_redirect('/');
} else {
//handle authentication errors
$this->view->loginMessage =
"Sorry, your username or password was incorrect";
}
} else {
//handle form validation errors
$this->_redirect('/users/index/register');
}
} else {
//if not post render empty form
$this->view->form = $form;
}
}
public function logoutAction()
{
$authAdapter = Zend_Auth::getInstance();
$authAdapter->clearIdentity();
}
http://www.ens.ro/2012/03/20/zend-authentication-and-authorization-tutorial-with-zend_auth-and-zend_acl/
Good Luck!
I'm trying to integrate my site with facebook connection to handle facebook signup and facebook login. i'm using codeigniter framework. But I got this problem now:
current facebook login user is "test1". I go to my site to sign up with facebook, everything works fine and "test1"'s info are stored in my database. However, after I log test1 out from facebook, and login "test2" in on facebook, I go back to my site and do a signup with facebook again, it still "test1"'s info stored.
I use ion auth library to handle user logout from my site. However, after I switch facebook test user accounts and do a "login with facebook" again, it still get the previous facebook user.
Based on the 2 cases above, it seems that the facebook session wasn't cleared up? I'm struggling on this problem for a long time, please help!
I user this to get user data:
$fb_usr = $this->fb_connect->user;
(it seems that no matter how the facebook user changs, fb_connect always return same user)
and fb_connect is sth like this:
<?php
include(APPPATH.'libraries/facebook/facebook.php');
class Fb_connect extends Facebook{
//declare public variables
public $user = NULL;
public $user_id = FALSE;
public $fbLoginURL = "";
public $fbLogoutURL = "";
public $fb = FALSE;
public $fbSession = FALSE;
public $appkey = 0;
//constructor method.
public function __construct()
{
$CI = & get_instance();
$CI->config->load("facebook",TRUE);
$config = $CI->config->item('facebook');
parent::__construct($config);
$this->user_id = $this->getUser(); // New code
$me = null;
if ($this->user_id) {
try {
$me = $this->api('/me');
$this->user = $me;
} catch (FacebookApiException $e) {
error_log($e);
}
}
if ($me) {
$this->fbLogoutURL = $this->getLogoutUrl();
} else {
$this->fbLoginURL = $this->getLoginUrl();
}
} //end Fb_connect() function
}
I think what you need to do is set the "next" param for your getLogoutUrl() call. Something like this:
$args['next'] = site_url('logout'); // replace "logout" with your controller which will clear the session
$fbLogoutURL = $facebook->getLogoutUrl($args);
Then, in the controller set as "next" you'll need to clear the session data.
class Logout extends CI_Controller {
public function index() {
$facebook->destroySession();
$this->session->sess_destroy(); // Assuming you have session helper loaded
$this->load->view('logout');
}
}
Let me know if that helps.