codeiginter no direct access to functions - php

I'm having this problem about direct access to functions: for example I have this code:
controller users
function index(){
//this is my users index view, user can add,edit,delete cars
}
function details($id){
//a function where 1 car can be viewed in detail..
function add(){
//function to add car
}
Now if I go to address bar and type. localhost/myapp/users/detail it will go to the url and echo an error since $id is null. What I want is only the index is directly accessible if a user would type in the address bar. I don't want the users to go directly to myapp/users/add, etc..

CI Controller functions always must be able to handle user input (i.e. url segments), which means anyone can type in whatever they wish and make a request. You can't stop that. The best practice is to either:
Always provide default arguments
Use the URI class to get your parameters, or func_get_args()
Always validate the presence of and integrity of arguments passed to the controller, as you would with any other user input
Since it's much more common, accepted, and easier to read - just make sure to always provide defaults and validate them.
An example with your controller:
function index() {
//this is my users index view
//user can add,edit,delete cars
}
function details($id = NULL) {
if ( ! $id) {
// No ID present, maybe redirect without message
redirect('users');
}
$user = $this->user_model->get($id);
if ( ! $user) {
// ID present but no user found, redirect with error message
$this->session->set_flashdata('error_message', 'User not found');
redirect('users');
}
// We found a user, load view here etc.
}
function add() {
// Check for the presence of a $_POST value
// You could also use the Form_validation lib here
if ( ! $this->input->post('add_car')
{
$this->session->set_flashdata('error_message', 'Invalid request');
redirect('users');
}
// Try to add the car here and always redirect from here
}
The only other way is to make the method private or use CI's _underscore() naming as suggested (making it inaccessible from the url). You can still call the function in other methods if you wish, as in:
function index() {
if ($this->input->post('add_car')
{
// Call the private "_add" method
$this->_add();
}
// Load index view
}
So to make a long story short: You can't stop the requests from being made, you can only decide what to do when the request is invalid.

Add an underscore before the names of functions you want to hide:
function _details($id){
//a function where 1 car can be viewed in detail..
}
function add(){
//function to add car
}

Related

Laravel allow route to be accessible only from another route

I have /signup/select-plan which lets the user select a plan, and /signup/tos which displays the terms of services. I want /signup/tos to be only accessible from /signup/select-plan. So if I try to go directly to /signup/tos without selecting a plan, I want it to not allow it. How do I go about this?
In the constructor, or the route (if you are not using contructors), you can check for the previous URL using the global helper url().
public function tos() {
if ( !request()->is('signup/tos') && url()->previous() != url('signup/select-plan') ) {
return redirect()->to('/'); //Send them somewhere else
}
}
In the controller of /signup/tos which returns the tos view just add the following code:
$referer = Request::referer();
// or
// $referer = Request::server('HTTP_REFERER');
if (strpos($referer,'signup/select-plan') !== false) {
//SHOW THE PAGE
}
else
{
dd("YOU ARE NOT ALLOWED")
}
What we are doing here is checking the HTTP referrer and allowing the page access only if user comes from select-plan
You are need of sessions in laravel. You can see the following docs to get more info: Laravel Sessions
First of all you need to configure till how much time you want to have the session variable so you can go to your directory config/sessions.php and you can edit the fields 'lifetime' => 120, also you can set expire_on_close by default it is being set to false.
Now you can have following routes:
Route::get('signup/select-plan', 'SignupController#selectPlan');
Route::post('signup/select-token', 'SignupController#selectToken');
Route::get('signup/tos', 'SignupController#tos');
Route::get('registered', 'SignupController#registered');
Now in your Signupcontroller you can have something like this:
public function selectPlan()
{
// return your views/form...
}
public function selectToken(Request $request)
{
$request->session()->put('select_plan_token', 'value');
return redirect('/signup/tos');
}
Now in signupController tos function you can always check the session value and manipulate the data accordingly
public function tos()
{
$value = $request->session()->get('select_plan_token');
// to your manipulation or show the view.
}
Now if the user is registered and you don't need the session value you can delete by following:
public function registered()
{
$request->session()->forget('select_plan_token');
// Return welcome screen or dashboard..
}
This method will delete the data from session. You can manipulate this. You won't be able to use in tos function as you are refreshing the page and you want data to persist. So its better to have it removed when the final step or the nextstep is carried out. Hope this helps.
Note: This is just the reference please go through the docs for more information and implement accordingly.

How to determine if a session with same variable is already there in laravel

I am using Laravel framework. There is a function in controller that creates session with name store_id
StoreController.php
function initiate($id)
{
//Some queries
session['store_id' => 'some value'];
}
Now if I run this function on one tab then session::get('store_id') is going on. But if I open another tab in the same browser then again run the function that means session('store_id') will be again set. How do I handle this situation that if there is already a session then it should redirect to it's perspective url.
Okay first of all, Bruuuhhhh been there and done that
Alright, lets begin. you want that if there is already a session with store_id going on then you want user to redirect or send back.
In your controller add this
public function initiate()
{
if(session()->has('store_id'))
{
//What ever your logic
}
else
{
redirect()->to('/store')->withErrors(['check' => "You have session activated for here!."]);
}
}
Most probably you would be wondering that user can just go to other url after /store/other-urls Yess he can.
To avoid this. Add a custom middleware
php artisan make:middleware SessionOfStore //You can name it anything.
In that middleware
public function handle($request, Closure $next)
{
if($request->session()->has('store_id'))
{
return $next($request);
}
else
{
return redirect()->back()->withErrors(['privilege_check' => "You are not privileged to go there!."]);
}
return '/home';
}
in your main store page. Add an anchor tag Stop Service
Now in your web.php
Route::group(['middleware' => 'SessionOfStore'], function()
{
//Add your routes here.
Route::get('/stop', 'StoreController#flushSession');
});
Now you have restrict access to urls and has checked the sessions.
Now in
public function flushSession()
{
//empty out the session and
return redirect()->to('/home');
}
The Laravel session helper has the function has to check this.
if (session()->has('store_id'))
{
// Redirect to the store
}
else
{
// Set the store id
}
The documentation contains all of the possible functions that can be used with the session helper.

How to redirect different page from same controller function in laravel 5.2

I want to redirect 2 different page from this controller function along with value.Here is my code. It works but both of time url become same.what shuld I do?
//in routes.php
Route::post('/','mycontroller#check');
// in controller.php
public function check(Request $request)
{
$c_email = $request->email;
$c_pass=$request->pass;
$c_type=$request->select;
$var=DB::select("SELECT * FROM reg where email = '$c_email' and Password = '$c_pass' and type = '$c_type'");
if ($var) {
return view('farmer')->with('user',$var);
// return redirect('farmer')->with('user',$var);
}
else {
$msg="Invalid login";
return view('index')->with('show',$msg);
}
}
If you want to actually redirect u can use the redirect() helper as statet in the official docs https://laravel.com/docs/5.3/redirects
You can also pass data
redirect('/my-route')->with(['user' => $var]);
The passed data can then be accesses through the session helper
$var = session('user')
HOWEVER, it seems like you have major issues in your code. Your password does not seem to be encrypted. Also there's no reason to use plain sql instead of eloquent here.
The route that is shown in the browser is defined in your
Route::post('/','mycontroller#check');
If you just return different views, the route does not change. You need to redirect to other views.
If you redirect to other routes you will ofcourse need to add / define them.
Route::get('/my-route', function() {}); // or post etc.

CodeIgniter form validation using session variables

How do I get the CodeIgniter form validation to validate the $_SESSION if there is no passed form data? I tried manually setting the $_REQUEST variable, but it doesn't seem to work.
i.e. I have a function search in the controller which validates the form input passed, and either returns you to the previous page with errors, or else moves you onto the next page. But I want this function to also work if you previously filled out this page, and the info is stored in the $_SESSION variable.
function search () {
$this->load->library("form_validation");
$this->form_validation->set_rules("flightID", "Flight Time", "required|callback_validFlightID");
$this->form_validation->set_rules("time", "Flight Time", "required|callback_validFlightTime");
$this->setRequest(array("flightID", "time"));
// adding session check allows for inter-view navigation
if ($this->form_validation->run()) {
// some application logic here
$this->load->view("seats", $data);
} else {
$this->logger->log($_REQUEST, "request");
// redirect back to index
$this->index();
}
}
function setRequest () {
// make sure none of the parameters are set in the request
foreach ($vars as $k) {
if (isset($_REQUEST[$k])) {
return;
}
}
foreach ($vars as $k) {
if (isset($_SESSION[$k])) {
$_REQUEST[$k] = $_SESSION[$k];
}
}
}
You can store the form post info in a session using the following codeigniter functions
$formdata = array(
'flightID' => $this->input->post('flightID'),
'time' => $this->input->post('time')
);
$this->session->set_userdata($formdata);
and the information can be retrieved with the following
$this->session->userdata('flightID')
$this->session->userdata('time')
form_validation works directly with $_POST, so use that instead of $_REQUEST.
What you're trying to do is setting Post values manually which is not natively
supported by CodeIgniter. So what we're doing first is extending the core.
Create a new file (MY_Input.php) and paste the following contents into it:
class MY_Input extends CI_Input{
function set_post($key, $value)
{
$_POST[$key] = $value;
}
}
That's a very basic implementation of your purpose but it's enough to test around. You might want to extend it to make it fit your needs (f.e. allowing the input of arrays).
So now. In your controller you can check if something has been posted by a user. If not you'll be just setting the post variable manually with your new method of the Input class.
class Some_Controller extends CI_Controller{
public function index()
{
// The user hasn't filled out a field?
if(!$this->input->post('a_key'))
{
// Let's set the postfield to the value of a session key
$this->input->set_post('a_key', $this->session->userdata('mystoredkey'));
}
}
}
After having set your postfield manually, it can be handled by the form validation library as it is meant to be.
That should be your way to go :)
You can really do some pretty things if you're not afraid of hacking the core. Many people are, don't be one of them!
Happy coding

Codeigniter session authentification still allows restricted page to load

I am trying to restrict access from a page if the user is not logged in. The weird thing is that the webpage, when tried to be accessed by an unauthorised user, shows the page for the restricted access (with the "unauthorised, please login" message and, on the same page, it loads the members only page).
For the site controller:
class Site extends CI_Controller {
function __construct(){
parent::__construct();
$isLogged=$this->session->userdata('logged');
if($isLogged!='logged' || !isset($isLogged)){
$data['content']='denied';
$this->load->view('include/template', $data);
}
}
function members(){
$data['content']='memberArea';
$this->load->view('include/template', $data);
}
The login form :
class Login extends CI_Controller {
function index () {
$data['content']='loginForm';
$this->load->view('include/template', $data);
}
function validateMember(){
// load the model for the login authentification
$this->load->model('loginModel');
//query should also contain the user details
$query = $this->loginModel->authenticate();
//if it returns something:
if($query){
foreach ($query as $row){
//set user data to be passed
$details=array(
'username'=>$row->user_name,
'id'=>$row->id,
'logged'=>'logged',);
}
//set session
$this->session->set_userdata($details);
redirect('site/members');
}
else{
$this->index();
}
}
The model for the login is:
class LoginModel extends CI_Model {
function authenticate(){
//select active fields
$this->db->select('id, user_name, password');
// query to select from table where conditions
$query = $this->db->get_where('login', array(
'user_name'=>$this->input->post('username'),
'password'=>$this->input->post('password'),),
1);
//if it finds something...must ask if i need to manually close the database with $this->db->close();
if($query->num_rows()==1){
foreach($query->result() as $row){
$data[]=$row;
}
return $data;
}
else {return false;}
}
}
My tests showed that site continues to call the other functions even if the construct function fails. the session does contain the data. If i use die() or exit() the webpages loads blank. many thanks in advance!
PS: the views only have <p> in them, nothing fancy.
I can see two solutions to this problem.
Redirect to another page that doesn't check for authentication. You can use redirect(<url>); from the URL helper.
Use exit() in the __construct() with the buffered output flushed. When you call $this->load->view() the data is sent to a buffer called output in CodeIgniter. You can write that buffer by doing :
if($isLogged!='logged' || !isset($isLogged)){
$data['content']='denied';
$this->load->view('include/template', $data);
// Write the output.
echo $this->output->get_output();
// Stop the execution of the script.
exit();
}
or you can by-pass the output buffer with:
if($isLogged!='logged' || !isset($isLogged)){
$data['content']='denied';
// Writes the content instead of sending it to the buffer.
echo $this->load->view('include/template', $data, true);
// Stop the execution of the script.
exit();
}
Pick which ever you want.
The constructor method does not "fail", the if statement is simply executed (because the condition is true) and there is no reason why this would prevent other methods from being executed.
Inside the constructor method, at the end of the if block, you may insert an exit statement, this way the page would probably behave as you are expecting.
See here http://php.net/manual/en/function.exit.php
You're testing if there is a query, not if the query actually return anything. Check the num rows and make sure they equal 1, doing greater than 0 is bad practice on login checks.
if($query->num_rows==1){
PS. Post your model code as well, it's possible the error is there and it's returning a result even when it shouldn't.

Categories