Jump to content

How to prevent direct url with php and mysql


PNewCode
Go to solution Solved by PNewCode,

Recommended Posts

gizmola has mentioned a better method for you to follow. using an empty value for a no is complicating the matter. true or false would be a better road. In the meantime, based upon your last post, then we need to change the logic to accomodate a not yes value (as long as the session salecheck exists.)

if (!isset($_SESSION['id']) || isset($_SESSION['salecheck']) && $_SESSION['salecheck'] !== 'yes') {
    header('Location: nosale.php');
    exit;
}

 

Link to comment
Share on other sites

@jodunno I just used your code and I'm still getting the same results. HOWEVER something you just said made me wonder... 

17 minutes ago, jodunno said:

(as long as the session salecheck exists.)

Does there have to be a statement somewhere that specifically says to make the 'salecheck' column a session?
The last post I showed has all the pages and all of the scripting that exists as of now

Edit: I have no doubt that gizmola has a better method, but I just don't know how to go about doing all that right now. I'll have to make a point to learn that. Right now I only know how to insert the word "yes" in that column for that user id :)

Edit 2: I should have mentioned too, while my site isn't huge yet, with only 80 members, I don't want to have to enter a "no" in each persons "salecheck" column, and then have to do that for each person every time someone signs up. So it's just easier to leave it blank and enter a "yes" when someone gets that extra perk :)

Edited by PNewCode
Link to comment
Share on other sites

your login system should only store the id of the logged in user in a session variable. this is the only session variable you should be using related to what you are trying to accomplish in this thread. you would then query the database table(s) on each page request to get any other user data, such as a username, user permissions, membership level, ... the reason for doing this is so that any change made to this user data will take effect on the very next page request (without requiring the user to log out and back in again.)

once you have the user data, or lack of, in an appropriately named variable (or instance of a class), you would use it, or lack of, in logic to control what the current user can do or see on the current page.

Link to comment
Share on other sites

as long as you are getting values from the db and assigning those values to the session, then this shouldn't be a problem. session_start is used and the data in the session should be accessible. Try to change the logic. By testing for a user id, we have to separate a visitor from a user, which we are not doing. We also have to separate a user into sale and nosale page, so more than one condition is required (especially to separate visitors from users.)

<?php 
  session_start();
  include_once "config.php";
  //and be certain that the session variables are set in this file

  if (!isset($_SESSION['id'])/*.*/) {
      //then we have a vistor, which should not see a yes or no page?
      header('Location: /'); //go to root page or wherever they should be in your design
      exit;
  }

 if (empty($_SESSION['salecheck'])/*.*/) {
      //then we have a user, which should see a nosale page
      header('Location: nosale.php'); //go to root page or wherever they should be in your design
      exit;
  }

  //then we have a user, which should not see a yes page
  echo 'this is the YES page view.';
 
?>

if this is not working then something else is breaking. Try to echo session variables to see that they exist and what are their values if they exist. How are you checking these values as they are assigned to a user?

$sql = "SELECT id, switch FROM sale"

where username = what? i do not see this information. Therefore, i assume that the session variables do not exist.

where is this login code? are you certain that you have set ALL of the necessary data before you present to us this problem?

look it over. think about it. 

Link to comment
Share on other sites

Systems backed by a relational database are very often overlooked when people are inexperienced, and suprisingly, they are often overlooked by experienced developers as well.

The reality is that the future of the system is tied to the decisions made when the database is first being designed.  I like to use the analogy of saying:  "people don't go and try and build a skyscraper on the foundation that laid for a one room mud hut" and yet that is what so often what happens.

I would suggest we take a step back from what you perceive as your problem and take a look at your database.  

Proper database design takes a fraction of the time that it takes to write the code that will use that design, and yet, it is so often the case that developers are in a hurry to implement something quickly that they don't take any time to design the database properly, arguing that it can be refactored later (which it never is).

  1. What database engine are you using?  I think it's mysql but I'm not sure
  2. What tables do you have
  3. What is the structure of these tables

With an understanding of that, we can probably help you fix any mistakes you made, and converse effectively about how and what you might need to add.

This will then lead to a better understanding of a specific functional problem you might be having.

 

Link to comment
Share on other sites

Sorry everyone. I'm sure you're ready to give me the "look" at this point haha.

So just to give a little background that you don't see in this thread...

There is a login page. People come to the site, they login, and then they can see the main page. It's working great and keeps the session for a lot of things to echo for their own things they can share on a chat page too. It shows their name when they post and all is wonderful with that (I'll post that below, the page after they login for the main page)

The database is full of lots and lots of things for pictures and chat posts and lots of stuff. So showing the whole database or changing it at this point would be altering over a year of work (I only took over the last few months and started learning that early too... previous developer had to be fired and I can't afford another one so I started learning it)
and possibly having to spend that much time readjusting all the pages that echo different things from it. So, thats why I was trying to center it down to just this one new thing I'm adding.

So the below works to show the page after they login (once they login, they are auto sent to this one)
What I'm attempting to do, is create another one just like it that only people that have "yes" in their column named "salecheck"

I'm SO greatful for all the help. The people here are amazing!!!!!!! Unfortunately I'm stuck at just trying to have to make this work without changing the database structure. If it's not possible it's okay. If thats the case, maybe I should just create a new website for those users however I was hoping to keep this all in one.

The below is working for what it is. I didn't add any of the store yet because I wanted to have the 2 levels of it working on the side before I made it public because I have 20 different businesses ready to let me list them for a commission

 

//////// WHEN THE USER ENTERS THE LOGIN CREDENTIALS ON THE WEBSITE, THEY ARE SENT TO THIS PAGE ////////

<?php 
  session_start();
  include_once "config.php";
  if(!isset($_SESSION['id'])){
    header("location: login.php");
  }
?>




<script>
document.addEventListener('contextmenu', event => event.preventDefault());
</script>

<style>
.ssm_opcion img {
  max-width: 100%;
  height: auto;
}
</style>



<style>
* {
  box-sizing: border-box;
}

.fab-wrapper {
  position: fixed;
  bottom: 3rem;
  right: 3rem;
}
.fab-checkbox {
  display: none;
}
.fab {
  position: absolute;
  bottom: -1rem;
  right: -1rem;
  width: 4rem;
  height: 4rem;
  background: blue;
  border-radius: 50%;
  background: #126ee2;
  box-shadow: 0px 5px 20px #81a4f1;
  transition: all 0.3s ease;
  z-index: 1;
  border-bottom-right-radius: 6px;
  border: 1px solid #0c50a7;
}

.fab:before {
  content: "";
  position: absolute;
  width: 100%;
  height: 100%;
  left: 0;
  top: 0;
  border-radius: 50%;
  background-color: rgba(255, 255, 255, 0.1);
}
.fab-checkbox:checked ~ .fab:before {
  width: 90%;
  height: 90%;
  left: 5%;
  top: 5%;
  background-color: rgba(255, 255, 255, 0.2);
}
.fab:hover {
  background: #2c87e8;
  box-shadow: 0px 5px 20px 5px #81a4f1;
}

.fab-dots {
  position: absolute;
  height: 8px;
  width: 8px;
  background-color: white;
  border-radius: 50%;
  top: 50%;
  transform: translateX(0%) translateY(-50%) rotate(0deg);
  opacity: 1;
  animation: blink 3s ease infinite;
  transition: all 0.3s ease;
}

.fab-dots-1 {
  width: 32px;
  border-radius: 10px;
  animation-delay: 0.4s;
  right: 50%;
  transform: translateX(50%) translateY(-50%) rotate(180deg);
}
.fab-dots-2 {
  left: 50%;
  transform: translateX(-50%) translateY(-50%) rotate(0deg);
  animation-delay: 0.4s;
}
.fab-dots-3 {
  width: 32px;
  border-radius: 10px;
  animation-delay: 0.4s;
  right: 50%;
  transform: translateX(50%) translateY(-50%) rotate(90deg);
}

.fab-checkbox:checked ~ .fab .fab-dots {
  height: 6px;
}

.fab .fab-dots-2 {
  transform: translateX(-50%) translateY(-50%) rotate(0deg);
}

.fab-checkbox:checked ~ .fab .fab-dots-1 {
  width: 32px;
  border-radius: 10px;
  left: 50%;
  transform: translateX(-50%) translateY(-50%) rotate(45deg);
}
.fab-checkbox:checked ~ .fab .fab-dots-3 {
  width: 32px;
  border-radius: 10px;
  right: 50%;
  transform: translateX(50%) translateY(-50%) rotate(-45deg);
}

@keyframes blink {
  50% {
    opacity: 0.25;
  }
}

.fab-checkbox:checked ~ .fab .fab-dots {
  animation: none;
}

.fab-wheel {
  position: absolute;
  bottom: 0;
  right: 0;
  border: 1px solid #;
  width: 10rem;
  height: 10rem;
  transition: all 0.3s ease;
  transform-origin: bottom right;
  transform: scale(0);
}

.fab-checkbox:checked ~ .fab-wheel {
  transform: scale(1);
}
.fab-action {
  position: absolute;
  background: #0f1941;
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: White;
  box-shadow: 0 0.1rem 1rem rgba(24, 66, 154, 0.82);
  transition: all 1s ease;

  opacity: 0;
}

.fab-checkbox:checked ~ .fab-wheel .fab-action {
  opacity: 1;
}

.fab-action:hover {
  background-color: #f16100;
}

.fab-wheel .fab-action-1 {
  right: -1rem;
  top: 0;
}

.fab-wheel .fab-action-2 {
  right: 3.4rem;
  top: 0.5rem;
}
.fab-wheel .fab-action-3 {
  left: 0.5rem;
  bottom: 3.4rem;
}
.fab-wheel .fab-action-4 {
  left: 0;
  bottom: -1rem;
}
</style>



<div class="fab-wrapper">
  <input id="fabCheckbox" type="checkbox" class="fab-checkbox" />
  <label class="fab" for="fabCheckbox">
    <span class="fab-dots fab-dots-1"></span>
    <span class="fab-dots fab-dots-2"></span>
    <span class="fab-dots fab-dots-3"></span>
  </label>
  <div class="fab-wheel">
 <a href="https://www.pnewcode.info/chat-v3/logout" target="_self" class="fab-action fab-action-1"> 
    <img src="assetimgs/menuicons/losm.png" width="37" height="31"> </a> <a href="help.php" target="_self" class="fab-action fab-action-2"> 
    <img src="assetimgs/menuicons/helpsm.png" width="37" height="31"> </a> <a href="account2.php" target="_self" class="fab-action fab-action-3"> 
    <img src="assetimgs/menuicons/accountsm.png" width="37" height="31"> </a> 
    <a href="home.php" target="_self" class="fab-action fab-action-4"> <img src="assetimgs/menuicons/homesm.png" width="37" height="31"> 
    </a> </div>
</div>







<table width="100%" border="0" cellspacing="0" cellpadding="0">
  <tr align="center" valign="top"> 
    <td height="738"> 
      <table width="100%" border="0" cellspacing="0" cellpadding="0">
        <tr align="center" valign="top"> 
          <td> 
            <table width="100%" border="0" cellspacing="0" cellpadding="0">
              <tr>
                <td align="center" valign="top"> 
                  <div class="ssm_opcion"><a href="twitchstuff.php"><img src="homeimgs/new/1.jpg" border="0"></a></div>
                </td>
                <td align="center" valign="top"> 
                  <div class="ssm_opcion"><a href="music.php"><img src="homeimgs/new/2.jpg" border="0"></a></div>
                </td>
                <td align="center" valign="top"> 
                  <div class="ssm_opcion"><a href="games.php"><img src="homeimgs/new/3.jpg" border="0"></a></div>
                </td>
              </tr>
            </table>
          </td>
        </tr>
        <tr align="center" valign="top"> 
          <td height="271"> 
            <table width="100%" border="0" cellspacing="0" cellpadding="0">
              <tr> 
                <td align="center" valign="top"> 
                  <div class="ssm_opcion"><a href="group-chat.php"><img src="homeimgs/new/4.jpg" border="0"></a></div>
                </td>
                <td align="center" valign="top"> 
                  <div class="ssm_opcion"><a href="help.php"><img src="homeimgs/new/5.jpg" border="0"></a></div>
                </td>
                <td align="center" valign="top"> 
                  <div class="ssm_opcion"><a href="basement.php"><img src="homeimgs/new/6-3.jpg" border="0"></a></div>
                </td>
              </tr>
              <tr> 
                <td align="center" valign="top" colspan="3">
                  <table width="100%" border="0" cellspacing="0" cellpadding="0">
                    <tr align="center" valign="top"> 
                      <td colspan="3"> 
                        <div class="ssm_opcion"><img src="homeimgs/bottom.jpg" width="1920" height="278"></div>
                      </td>
                    </tr>
                  </table>
                </td>
              </tr>
            </table>
          </td>
        </tr>
        <tr align="center" valign="top"> 
          <td> 

          </td>
        </tr>
      </table>
    </td>
  </tr>
</table>

 

Edited by PNewCode
Link to comment
Share on other sites

33 minutes ago, PNewCode said:

and possibly having to spend that much time readjusting all the pages that echo different things from it. So, thats why I was trying to center it down to just this one new thing I'm adding.

It's great to get some context on your problem, but then you follow that up with a page of markup.

So let's be clear about the database.  If you have a bunch of tables that aren't relevant to this feature, that's not at issue.  What I asked for is the tables that are relevant.  The tables that effect login, and membership level and this "sale visibility flag" or whatever it is that you are trying to do here.  What you provided previously is useless without context.

  1. id
  2. salecheck (varchar)

This is a useless table, which can't possibly be useful, unless there is something else you haven't explained.  If these are just columns in a user table, then I can tell you the structure of this feature is wrong, and will never be useful, but so far we haven't gotten to that point yet.

I've been developing systems for a living for decades, for companies large and small in the entertainment, gaming and telcom industries, as well as a number of consumer startups.  I tell you that your problem is likely in/related to the database structure (or lack thereof) and you say:  Database is fine.

I say: don't use a varchar to store a boolean, and you say that is too much trouble to change, when the fact is, not only is it not too much trouble, but could have been done and taken into account within 10 minutes tops. 

You say:  I need a default value, so I don't have to set it, after I already stated, a flag should be a tinyint with default of 0 (ie. false).  Of course it's not even clear now that a flag is what you need here, since it's not clear what the use case is.

The difference between us, is that I have designed databases used in systems that served 100's of millions of people, and you haven't.  This is not hyperbole, as I designed the underlying database used by one of the most successful multiplayer games ever, and that served 10's of millions of players and an untold number of games at this point.

When we have people with problems like yours telling us how to help you, that never ends well.  We've been helping people for over 20 years, so we know a thing or two about it.  Just because you have an irrational fear of changing things in the database design, isn't going to change the fact that doing so, when you know what you are doing, as most of the developers who visit this site and help people do, it is not only not dangerous or problematic, but it is also much better than trying to add spaghetti code to work around the problem.  We know what is hard or dangerous.

When you describe your system, which as I understand it has:

  • Members
  • Levels of membership
  • Companies
    • Company Promotions

 

And you have a feature where you want to be able to have company promotions/sales that are shown to members of a certain membership level, that is not a difficult design problem.  It's a variation of what every site that offers affiliate links does (although very few have reason to secure this away from people.)  If there is a wrinkle to this that isn't clear here, you'll have to forgive me, because this has been a process of peeling the onion, in order for us to get at what that problem actually is.  You want to fix it, we want to help you, but you have to be willing to meet us halfway.

 

Link to comment
Share on other sites

@gizmola I deeply apologize for how I must be appearing to come accross. Trust me I definitely see everyones skill to being far beyond me and I am extremely appreciative for and all advice. I promise my intent is not to push back.
Whenever I say I can't redo it all, it's because with my lack of skill I could potentially mess up a lot of other pages that I wont know how to fix (which also use the database to echo certain things, call on other things, etc).
So it's really just a literal fear that if I mess with it, I'll do damage that I wont know how to undo or even have an idea on how to fix. I promise that is the only reason I hesitate or say "I can't" with things. I DO feel like you are correct in what you're saying and that it would be better for me to follow it all. I just literally can't afford to have the website crash or malfunction if I mess with the database to alter other tables and stuff.
Like I said, it's just fear and lack of experience. I promise. I meant no disrespect.

That being said, with this lack of experience, I'm just staring at the page like a deer in headlights right now because I'm not exactly sure what I should be showing anymore haha. I thought showing a working page, then describing what I want to do would do the trick, but I am mistaken.

So another reason I don't want to have a default value is because the login is done through laravel. I have absolutely zero clue how to add a default value to new members that sign up. I looked through all the folders and I can't make any sense of any of it. I didn't create it. The developer I had to fire did. SO, thats why I am stuck making columns in tables with empty default values, and updating them as I go. I hope to one day understand how to do a better way but for now I don't. Perhaps the next idea I have I can do some junk files on the side to learn with but this one I'm running out of time on.

So, That might explain a little of why I'm so BLAH to doing the suggestions, and I apologize for that. I would be happy to tell you and show you all that you need. For now, I'll post something below, and please let me know what else you would like to see, and know that while I'm getting old, I'm just a kid with this stuff haha.


Here is the Database "set_three"
image.png.4e0a5a0316ca765f1b135157bff6c13d.png

Here is the table "users" .... Note that "modcheck" is now called "salecheck". This is a screen shot from this morning before I changed the name
Also, a lot of these tables aren't being used for this. Email and all that stuff is for a different website structure that isn't relevant to my current issue or even the main website. But a different project completely
I did not build this database either

image.png.d735b21dc07cc3c9d37ecaf26d0a2605.png

Here is a screen shot of the rows that are being used for this in the table called "users" that is most relevant to what I am trying to do in this thread

db.png

Link to comment
Share on other sites

33 minutes ago, gizmola said:

When you describe your system, which as I understand it has:

  • Members
  • Levels of membership
  • Companies
    • Company Promotions

This is basically what I'm creating. Right now it has members, and pages for them to view once they are logged in.
What I am trying to add is a store that those same members can view. But if they buy the extra sales perk, they get access to see the special sales page :)

Link to comment
Share on other sites

Hello again,

I have tried to help you for a few hours yesterday. I am not a php specialist and my database skills are kindergarten level, so i advise you to follow the lead of the specialists in the forum, such as gizmola. Barand is also a db wizard. Requinix is just awesome in my opinion. Not trying to leave anyone out because we have access to many skilled coders here that post tips and code regularly. You don't have to build your program with someone elses design but you should definitely follow leads and correct code that isn't working or is insecure et cetera.

Obviously, the session variables are not set. You know that because a simple isset check redirection always redirects you (the 'is not set' is true). I cannot see how you are associating a switch with a user in the first place. When a user logs in, how do you handle this action? you check the db for a password where username/email matches a form post named username/email. Password verify the password, then a user is logged in. Now what do you do? If you need user associated data then you must associate this data with the user at login. An id column is usually how coders IDentify a user. So the session should have a $_SESSION['id'] set at login (identify the logged in user).

Then your switch query would be 'SELECT switch FROM sale WHERE id ='. you have to complete the WHERE id = part. An example using pdo with a session variable loaded into the session at user login verification:

$varSESSIONid = $_SESSION['id'];
 
$servername = '127.0.0.1';
$username = '';
$password = '';
$dbname = '';
$att = array(
    PDO::ATTR_EMULATE_PREPARES => false,
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
  );
// adjust the charset to whatever you have implemented

$conn = new PDO("mysql:host=$servername; dbname=$dbname; charset=utf8mb4", $username, $password, $att);
$sql = 'SELECT switch FROM sale WHERE id = :sessionID';
$req = $conn->prepare($sql);
$req->execute(array(':sessionID' => $varSESSIONid));
$row = $req->fetch();
$_SESSION['salecheck'] = $row['switch'];

then you would have the switch associated with the logged in user ($_SESSION['id'], if this is what you are doing with id). once you fix your database problems, your switch will be working. You can see that the following code works by simply uncommenting/commenting the various arrays in a development server such as xampp.

<?php declare (strict_types = 1);

// this is a switch.php page example
// you also need a nosale.php file and a sale.php to test this code

(array) $_FakeSESSION = ['id' => 1, 'salecheck'=> 1];
//(array) $_FakeSESSION = ['id' => 1, 'salecheck'=> 0];
//(array) $_FakeSESSION = ['id' => 1, 'salecheck'=> true];
//(array) $_FakeSESSION = ['id' => 1, 'salecheck'=> false];

if (!isset($_FakeSESSION['id'])/*.*/) {
    // change the isset variable to $_SESSION['id'] when you fix your db/session issues
    echo 'visitor page view'; exit;
}

require_once empty($_FakeSESSION['salecheck']) ? 'nosale.php' : 'sale.php';
// change the empty variable to $_SESSION['salecheck'] when you fix your db/session issues
// the switch will work when the database code is adjusted.

I suggest that you repair your database and the code that is associated with the login script. You need a user id and you need to use that id to query id specific data from the db.

Best wishes.

Link to comment
Share on other sites

13 hours ago, PNewCode said:

So it's really just a literal fear that if I mess with it, I'll do damage that I wont know how to undo or even have an idea on how to fix.

This is why you need to be doing your work in a local development environment and keep your source under a version control system such as git.

By doing that, you don't need to fear breaking anything.  If you ever feel things are not working out, you can just roll-back your changes and start over.  Only when you have everything working properly do you then publish the changes.

 

Link to comment
Share on other sites

  • Solution

AND IT'S DONE!
I want to thank everyone that gave so much awesome education and help on here. Between that and an unreal amount of research, I present to you the working solution. I hope this helps anyone else that might be at my level (inexperienced and new)

I put this at the top of the page and TADA it works!

First it checks if the person is logged in. If not then they are sent to the login page.
Then when they return to this page, it checks if "yes" is in the "salecheck" column for their id
If it is, then they see the rest of the page
If it is not, then they get sent to a "nono.php" page that tells them they don't have access and the option to purchase the access
Once they purchase it, then "yes" is entered in the database for their id, and they can see the contents of that page

I COULD NOT HAVE DONE THIS WITHOUT YOU ALL! THANK YOU! (and now I need a nap)

THANK YOU ALL AGAIN! I APPRECIATE YOU ALL VERY MUCH!!!
 

<?php 
  session_start();
  include_once "configure.php";



if (!isset($_SESSION['id'])){
header("location: login.php");
 }else{

  $hostname = "localhost";
  $username = "Removed for posting";
  $password = "Removed for posting";
  $dbname = "Removed for posting";


  $conn = mysqli_connect($hostname, $username, $password, $dbname);
  if(!$conn){
    echo "Database connection error".mysqli_connect_error();
  }
$user_id = $_SESSION['id'];
  $sql = "SELECT * FROM users WHERE id = '$user_id'";
  
  


$result = $conn->query($sql);

if ($result->num_rows > 0) {
  // output data of each row
  while($row = $result->fetch_assoc()) {
    $modcheck =  $row["salecheck"];

  }
} else {
  echo "0 results";
    die();
}
if($salecheck == "yes"){
}else{
	header("location: nono.php");
}
}

?>


////// here is the gobblty gook html that will show the extra sales perks on the same page as the scripting above //////

 

Edited by PNewCode
Additional info
Link to comment
Share on other sites

3 hours ago, PNewCode said:
if (!isset($_SESSION['id'])){
header("location: login.php");
 }

You need to get into the habit of calling exit; after you do a redirect with header().  Calling header does not stop the script, it will continue to run, potentially doing things you don't want it to.  For example, if you had:

//Redirect if not logged in.
if (!isset($_SESSION['id'])){
   header('Location: login.php');
}

//...
//Delete the selected user.
$sql = 'DELETE FROM users WHERE Id=?';
$stmt=$pdo->prepare($sql);
$stmt->execute([$_POST['id']]);

The script will still delete the record, even if the nobody is logged in, because you didn't exit;.

 

  • Like 1
Link to comment
Share on other sites

<?php 
  session_start();
  include_once "configure.php";

if (!isset($_SESSION['id'])){
header("location: login.php");
 }else{

so why include the db config file if the user is a visitor?
why use an else clause when the page is by now redirected (if exit is used)?
and again, what kicken typed to you regarding the use of exit.

i recommend installing xampp on a personal computer and recoding your website and database to version 2.0. You have alot to learn, young Jedi.

Best wishes,
John

Link to comment
Share on other sites

@kicken You're right I should have for best practice. @jodunno has been telling me that too and I forgot.  For some reason it works even without that though. If they aren't set to have that permission in the database then they can't see the page. But still, I am going to add that after headers for best practice. Thank you :)


@jodunno just for some explanation, the database is included because no visitor is allowed to see the website at all without logging in. So it checks that first. The only other redirect that is happening is if they try to access that page and don't have the permission for that extra page in the database :) It's working perfectly now. I'm even adding this as an admin access for one of my other sites that gets used more.

I learned a lot on this thread. Its awesome!

Link to comment
Share on other sites

35 minutes ago, PNewCode said:

For some reason it works even without that though. If they aren't set to have that permission in the database then they can't see the page.

The redirect happens because the header gets sent, but that doesn't happen until the script is finished.  The point of the exit is to force the script to end.  As this whole thread has been about, "they can't see the page" is not a valid defense, they can still access it directly by url.

I did a code review for a company once that had the exact problem I described in their CMS.  I demoed the problem to them by creating a test page in the admin area then logging out.  Without logging in again I typed in the URL to their delete page with the ID of the page I created.  I got redirected to the login page, everything seemed fine but. After logging in though, one could see that the page had in fact been deleted.

Link to comment
Share on other sites

@kicken I added the exit; because I know you are all much wiser than me for this. But I also wanted to share with you, that I just added all this to work as an admin page on my other site and it works the same. Even without the exit at the end, it still does as it's supposed to. If you go directly to the url, it just spits them back to the other page if they don't have the "yes" for that value in the database column. I made a test account that doesn't have that credential and one with it. And it does as it should. Without that credential that is auto detected, they can't see the page and are redirect to a "nono.php" page.

However, I put the exit back on anyways just to stay with what I'm learning here, but I see no difference in the function when using the page. Just wanted to share that with you :)

Link to comment
Share on other sites

2 hours ago, PNewCode said:

but I see no difference in the function when using the page.

Because you're only looking at and considering what the browser is doing.  As I said, the redirect will work fine, just like it did when I was doing my demo to that company.  The problem is that without the exit, any other code in the page after the header will still run.  How much of a problem that is, depends on what that page does. In the case of the demo, that code deletes data which is very bad. 

If you want to try get a better understanding is to use something like curl to request your URL rather than the browser.  A browser that sees a Location: header ignores any other output and just requests the new URL.  Using curl, you can see the rest of the output.  So request your page using curl with and without the exit and you'll see the difference.

curl -ik https://example.com/yourpage.php

 

  • Like 1
Link to comment
Share on other sites

On 2/26/2023 at 8:54 AM, PNewCode said:

@kicken I added the exit; because I know you are all much wiser than me for this. But I also wanted to share with you, that I just added all this to work as an admin page on my other site and it works the same. Even without the exit at the end, it still does as it's supposed to. If you go directly to the url, it just spits them back to the other page if they don't have the "yes" for that value in the database column. I made a test account that doesn't have that credential and one with it. And it does as it should. Without that credential that is auto detected, they can't see the page and are redirect to a "nono.php" page.

However, I put the exit back on anyways just to stay with what I'm learning here, but I see no difference in the function when using the page. Just wanted to share that with you :)

 

The point of the exit is, consider this pseudo code

  • Do thing 1
  • Do thing 2
  • exit
  • Do thing 3
  • Do thing 4

So with an exit, there is no way for execution to get to thing 3 and thing 4.  

The key thing that might help you understand, is where code is executing.  This is difficult sometimes even for developers who are actually working in web development as kicken's story illustrates.

In your case, "Do thing 2" is actually: set a browser header to tell the browser/client to redirect to a new html page.  This is the way the HTTP protocol works.  The user/client's browser makes a request, and the server sends a response.  These request/response chains happen as rapidly as possible, and the underlying network connections are opened and closed as soon as the request and response are completed.

The problem here, and the reason you NEED an exit, is because, it is entirely up to the browser to perform the redirect and reload.  In other words, sending the redirect header in a response is the server "trusting" the client to do the right thing.  So when you say it works, that is because in a typical scenario, the browser does make the redirect as requested.  

One of the many difficulties in web development is that the client can "never be trusted" to do what it is supposed to do.  There are all sorts of methods and tools that people can use to emulate an HTTP client.  In fact, serverside code will often emulate a client for the purposes of doing things like talking to API services or electronic payment gateways.

People often also mistakenly think if they add javascript (which runs in the client browser) security and validation routines, then this secures a page, when in fact, these same tools can run pages without running javascript, and thus bypassing the javascript validation and security.  Again, the rule of thumb is "client data can not be trusted".

This is also the same area where SQL injection bugs catch people:  because they accepted client data, and trusted that it was appropriate without validating it first.

So to summarize, you won't see something different with an exit, because the client does its redirect as expected.  However, without the exit, the script continues to run on the server until it completes.  At best that's just some wasted execution time, but at worst it could be entry into entire sections of code you didn't expect it to.

If you have a logging/debugging feature in your code, where you could log out messages, you could put a logging line directly after the redirect and you would see that it would log out a message, even though the header() function runs, and the client accepts that and redirects.  

One amazing tool that everyone has available to them, is the developer tools built into most of the major browsers.  All of them have a network tab.  Getting familiar with that tab is a huge help in understand how HTTP works and how your code works.

 

Here's a screen shot of the developer tool window in chrome, open to the yahoo.com homepage.  I've clicked on the main get request, showing what my browser sent as a request.  From here I can look at the response, as well as all the subsequent requests that came from my browser once the html was delivered from the server.  This is because all the individual components of the page (css, javascript, images, videos) are loaded separately from the html that references them.  This excludes js and css that were embedded in the page, but rarely do people do that, and typically are making references to load those resources.

 

yahoo_home.jpg

This is an amazing tool that anyone who is doing any sort of development should use regularly during development.  You can see here, the important HTTP elements:  Request/Method (Get,Post, etc), status code.  The server and port that the request was sent to.  You also can see response headers here from the server.  You could check the Cookies tab to see the cookies sent by the server, and the response data in the response tab, to see what the server sent in response.

Once you get a real understanding of how the web actually works via HTTP, many things become clear.

 

  • Like 1
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.