Jump to content
Larry Ullman's Book Forums

Recommended Posts

On page 451 it says PHP 5.5 is needed for password_hash().  So I had my Web host upgrade from v5.4.9 to v5.5.38.  Then I ran phpinfo() and got the following and don't know if it includes the right function for password_hash() or not.

 

hash support  enabled  

Hashing Engines  md2 md4 md5 sha1 sha224 sha256 sha384 sha512 ripemd128 ripemd160 ripemd256 ripemd320 whirlpool tiger128,3 tiger160,3 tiger192,3 tiger128,4 tiger160,4 tiger192,4 snefru snefru256 gost adler32 crc32 crc32b fnv132 fnv164 joaat haval128,3 haval160,3 haval192,3 haval224,3 haval256,3 haval128,4 haval160,4 haval92,4 haval224,4 haval256,4 haval128,5 haval160,5 haval192,5 haval224,5 haval256,5
 
Then from chapters 3 and 9 about dynamic web sites I created a student registration page which uses:
$pwd = password_hash($pwdkey, PASSWORD_DEFAULT);
 
$sql = "INSERT INTO student (userid,firstname,lastname,street,city,state,zip,user,eaddr,pwdkey) VALUES ('" .$userid. "','" .$firstname. "','" .$lastname. "','" .$street. "','" .$city. "','" .$state. "','" .$zip. "','" .$user. "','" .$eaddr. "','" .$pwd. "')";
 
In testing when the processing got to password_hash the screen blanked out and it went to "never-never-land" and that was it.  Either the version my host installed doesn't have password_hash() or something has to be hooked up.  From echoing I knew that it had reached that statement and had gotten no further.  My Web host says that "we don't debug people's programs" so about all I can ask them is "do you think it's working like it should?"
 
  
Link to comment
Share on other sites

Sorry.  I included mysqli_connect.php on page 270 to improve on what I've used before.  Then to follow the reading and start thinking security I used "require(../etc)" shown on page 278 to make sure the path started at the root and then down a level.  Next when everything froze up I thought it could only be the hashing.  However, the ../ ensuring It began at the root was the culprit.  When that was corrected password_hash() worked just fine.  Chapter 3 is about Dynamic Web Sites.  Does dynamic have anything to do with SPA (Single Page Application)?  Also, to make it dynamic isn't Ajax and jQuery commonly necessary?

Link to comment
Share on other sites

Ah, kudos for figuring it out and thanks for letting us know! 

 

As for "dynamic" it's not quite the same as a SPA. An SPA is made using JavaScript and, normally, an entire JavaScript stack (like React or Vue, based upon Node.js). But these are dynamic still in that the same page can do different things based upon criteria of your choosing.

Link to comment
Share on other sites

I'm starting to program the  login process and have a few relevant questions.  The first is why do the forums require a username whereas the book uses an email address instead?  I thought emails were more common these days.  The second deals with the purpose of includes.  For reuse it makes sense for maintenance, but I've found if one little part is different, then a separate include is necessary.  Includes are nice to simplify the main part, but if they then complicate things by their isolation they make it harder to test and find errors.  The last question is about specifying a path with ../ or not.  Keeping track of where the program is at to know whether to go to a subfolder or up to the parent is tricky.  I thought that a slash at the start of a path always meant starting at the root.  But I'm wondering if PHP itself has rules of its own or do all host's operating systems use an industry standard?

Link to comment
Share on other sites

These forums are third-party software and while I agree using the email address is fairly common, it's not universal. 

 

It's not clear what your question is about includes, but, yes, there is a trade-off to using them. Arguably over time you'll learn techniques that will overcome some of the downsides of using includes.

 

Yes, starting with a / means you're starting at the root. The only difference I'm aware of is I'm not positive what / does for Windows servers. 

Link to comment
Share on other sites

RE: includes.  Your example puts the database parameters and connection in a separate file and requires it.  I put that file in a scripts folder at my Web host and the main page is at the top which is where I get into using "/" or "../".  But in tests it produces a #500 server error at the host.  I contacted them to see if they have PHP errors activated and they do.  I've tried all kinds of path combinations for the include to no avail.  Then when I replace the include with the hard code the database access works and there is no server error.  At first I used DEFINES like you use in your example and then wondered whether that is only class oriented and works only at certain locations in a program.  So I switched back to the way I coded everything at first and it worked fine.  There are some particulars using includes for certain things that I must be unaware of and don't understand.  Unless I can figure out the mystery I'll have to work on it later when I have time, but at least I know what will work.

Link to comment
Share on other sites

Ah! An initial slash refers to the root of the operating system, which is not the same as the root of your web directory. And, to be clear, ../ goes up one directory. It sounds like maybe your database connection include is in a folder in the same directory as the including file, which would mean you shouldn't use ../ either. 

Link to comment
Share on other sites

With Windows I've always treated "root" as the top level with main pages so when I use "/" at the start of the path it creates an absolute starting place which is the root.  I've always assumed that a Web host isn't going to let you up any higher than your domain's root location.  In beginning textbooks PHP always seemed to call their pages "scripts."  So I put, for example, connection pages in the scripts folder which is accessed by /scripts/connect.php.  But includes also have PHP extensions, so they could be considered scripts too, however their purpose may have a more important "include" role.  I resorted to putting the connection variables in a place in the scripts folder, and the actual connection code remains in the main page.  Even if it's in the directory structure, you can't run that page and see the parameter data because it looks like it can't be viewed that way.  I don't know what difficulties were involved doing it the first way, but this second way works, and even looks more straightforward.

Link to comment
Share on other sites

Yeah, the web host isn't going to let you put scripts in the root, which even the admin shouldn't do. There may often be some confusion here between the "web root directory" and the computer's root directory. For anything handled over HTTP/HTTPS, a / refers to the web root directory. For anything in PHP, a / refers to the computer's root directory. 

 

For what it's worth, if you're going to do much developing in PHP, you really ought to make sure you grasp all this and learn to be okay with working with included files. It's a pretty basic and key concept for all development. I also really prefer not to have things like database details in a PHP script in your web directory, but it sounds like maybe you have no choice on that. 

Link to comment
Share on other sites

Thanks for the help.  I thought when you uploaded files to directories at your web host and executed

 programs there, the paths were synonymous so there was nothing to worry about.  For example, when I developed some stuff with ASP.net I always had to be concerned with closing connections because there is the error of "maxed out the number of open connections."  Apparently PHP closes them when to program finishes so there isn't the same concern.  I was curious so I reviewed Script 9.2 on page 271.  Line 14 says "... OR die('Could not connect etc').  I wasn't using the "OR" but was using "if(mysqli_connect_error() {(echo "No connection because etc).  Then after the include I continued with "else {" and then code from my program.  Your mysqli_connect.php doesn't have a ?> close.  Could my maybe having closing with ?> short-circuited processing so the program never continued?  Or could the "die" v. "connect_error" language have complicated things too much?  That's why my brain is still fuzzy about includes everywhere.
Link to comment
Share on other sites

  • 2 weeks later...

Since this is an open thread and you answer quickly I'll put an errata question here.  On page 456 of chapter 13 statement 55 gets the user_id and first_name.  Then in statement 65 it refers to $row['pass'].  But in order to verify, it would have had to select the stored password which wasn't selected, so I was wondering if the first name selected should have been the password.  The entry of the password text by the user apparently is VERIFIED by PHP comparing it to the hashed password which is in memory having gotten it from the SELECT.  I'm studying to use it now, and it could be "over my head" so I'm not seeing the big picture.  But they say "there's no such thing as a stupid question."

Link to comment
Share on other sites

It's funny I thought maybe the first name was questionable.  I was learning the password stuff first and wasn't thinking cookies/sessions.  Then I saw that the name was stored in the cookie.  There sure are a lot of modules going from the first password page and then to the login page using the functions and on to logged-in etc.  Of course, at the end of the book there's the AJAX approach.  I guess the larger the business the more compartmentalized it all is where each module is used by everyone in their own way.  It's mind-boggling to try to figure out which approach to use depending on whatever the situation.  It must be like learning a language where you can't really speak intelligently until you know all the basics and are fluent.

Link to comment
Share on other sites

Password.php (script 9.7) is a standalone page because its FORM posts back to itself.  It has an organized framework starting with testing for POST and then validating the input.  If error free it tries to find a match using the email and password fields.  Then if so, action is taken.  If not, then matching and/or system errors are printed as well as validation errors.  But it is not an included page.  However, it could be streamlined using login_functions_inc.php.  Check_login handles input validation, matching and error reporting.  Therefore why not just make calls to those functions from the main page to simplify the look of the code?  Next, login_page.inc.php (script 12:1) proceeds to modularize.  The comment says "it creates the entire login page."  But it doesn't even post to itself and you'd think at least validation would be done in the same place where the form exists.  It gets posted to login.php which takes control (but wouldn't have been called to start it off) and then includes login_page.  The comment says it "processes the login form submission."  Check_login lumps together validation, matching, and returning almost looking like password.php which hopefully was meant to be streamlined.  I can't see what is meant to be an improvement since the modularization seems to have just gotten more complicated.  So I can only conclude that in a big company it is necessary to create substantially-sized modules so everyone can piece them together as needed in a "black box" scenario.

Link to comment
Share on other sites

Well, they're different examples in different chapters, and the context for both is different. I wouldn't do too much apples-to-oranges comparison at this point. Rather, wait until the later example chapters in which everything is put together. And, to be clear, Script 9.7 cannot use the login_functions.inc.php logic because that's not created for another three chapters. 

 

Generally speaking, there is an argument--regardless of company size--in modularizing as much functionality as possible. By doing so you improve re-usability and make maintenance and debugging easier. 

Link to comment
Share on other sites

In the beginning it seemed to me that PHP was creatively free-form.  In Applesoft Basic they progressed to top-down design and ASP.Net has serverside processing and ViewState.  In a PHP book I read an author saying "a script that submits to itself means . . . you're not going to get a true MVC pattern.  You might need to simply accept that PHP is often going to cause you to sacrifice really clean MVC at the altar of getting things done."  I guess that means that a PHP shop doesn't necessarily have an industry standard as long as it works.

Link to comment
Share on other sites

Yes, one of the strengths of PHP is you can use it in many different ways. If you want to go the MVC route, you can do that. You can use frameworks or not. You can use OOP or not. I would do any of the above given the particulars of the project.

Link to comment
Share on other sites

Chapter 13's login_functions.inc.php uses:

   $q = "SELECT user_id, first_name FROM users WHERE email = '$e'";

   if(password_verify($p,$row['pass']))

 

I coded something different which should be the same:

   $eaddr = filter_input(INPUT_POST, 'eaddr', FILTER_SANITIZE_EMAIL);

   $pwdkey = filter_input(INPUT_POST, 'pwdkey', FILTER_SANITIZE_STRING);

 

$pwd = password_hash($pwdkey, PASSWORD_DEFAULT);

$sql = "SELECT user FROM student WHERE eaddr='" . $eaddr. "' AND pwdkey='" .$pwd='" .$pwd. "'";

if($result = mysqli_query($dbc,$sql))

 

I have to test it more ,but since the query didn't return any rows, it makes me think that a hashed form input being compared to a 256 byte hashed data field in the database is too much to ask.  Perhaps your approach is less intensive and/or easier.

Link to comment
Share on other sites

The password is encrypted by password_hash() using an automatically generated salt--a random value that makes the encryption more secure. If you execute password_hash() twice on the same password, you'll get two different results. This is why your query isn't returning any matches and why you have to use the password_verify() function instead. 

Link to comment
Share on other sites

     I tested according to the book's example and it worked the first time.  I thought there might be duplicate emails so it made sense to search for both email and password at the same time.  It occurred to me that PASSWORD_DEFAULT would use different salt codes each time and I'm happy to find out my logic is working.

     What's helped me with validation is jquery.validate.min.js and jquery.validate.password.js so thought I'd pass it on.  But I must say the bootstrap-navbar css you use would take some study to fully understand it.  Do large groups of people use all of that as if it's an industry standard?

     Also your other book with sticky forms uses the syntax

<input name='eaddr' type='email' id='eaddr' value='<?php print $eaddr; ?>'>  However I encountered in another book

<a href='<?php echo $email; ?>> etc.

Are the commands echo and print exactly synonymous so is it just a matter of programmers' preference?  Here they save directly in the value property via the php script.  But in JavaScript you'd use getElementById, or with jQuery via Ajax responding to an event, you could use $('#eaddr').val(obj.eaddr).  However you can't "call" an event so php's echo/print becomes more powerful than it's nomenclature connotes.  Also I read about Immediately Invoked Function Expressions.  But since php has server-side interpreter scripting it seems that an IIFE would be unnecessary.

Link to comment
Share on other sites

One question leads to another.  Script 12:1 posts to itself with <form action='login.php'>.  Then if successful there is setcookie('user_id', $userid).  But a cookie is on the client, so when redirected to loggedin.php (script 12:4) there is "if(!isset($_COOKIE['user_id]))" which means the client has passed the cookie to the php server for the test.  I read somewhere that the user id value can be passed in a querystring with "header('Location: whereto.php?user_id' .$userid);"  Then a cookie is unnecessary because of "$user_id=$_REQUEST['user_id]"  Cookies probably aren't that secure, but I suppose parameters being passed aren't either.  That is why you say on page 404 "for most web apps use sessions."

Link to comment
Share on other sites

Could you clarify what the actual question is?

 

But just to point something out, the reasons using cookies is better than passing the value in the URL are:

1. Cookies are definitely more secure and less obvious than doing that.

2. Cookies are more reliable than passing in the URL. If your site depends upon this value, every link and every form submission must be certain to continue to pass along the value. 

Link to comment
Share on other sites

 Share

×
×
  • Create New...