mod_rewrite working agaisnt my PHP Logic

I’m having some trouble with my mod_rewrite fighting with my PHP code and not giving me the outcome I’d like.

Here is my original mod_rewrite, whose purpose was to take a “Pretty Article URL” and transform it into something PHP can handle…

RewriteRule articles/([a-zA-Z0-9_-]+)$ articles/article.php?slug=$1

This has been working fine, but when I re-wrote my PHP to be more security conscious, some of my PHP isn’t firing, because the mod_rewrite steps in.

Here is an outline of my “article.php” code…


<?php
	// Attempt to Retrieve Article.
	if (isset($_GET['slug']) && $_GET['slug']) {
		// Slug found in URL.

		// Check Slug Format.
		if (preg_match('~(?x)			# Comments Mode
					^						# Beginning of String Anchor
					(?=.{2,100}$)				# Ensure Length is 2-100 Characters
					[a-z0-9_-]*			# Match only certain Characters
					$				# End of String Anchor
					~i', $_GET['slug'])){
			// Valid Slug Format.

			// Find Article Record.


			// Check # of Records Returned.
			if (mysqli_stmt_num_rows($stmt1)==1){
				// Article was Found.


			}else{
				// Article Not Found.
				// Display Error Page.

			}//End of FIND ARTICLE RECORD

		}else{
			// Invalid Slug Format.
			// Display Error Page.

		}//End of CHECK SLUG FORMAT

	}else{
		// Slug Not found in URL.
		// This will never fire!!
		// Apache catches missing slug and re-routes to "articles/index.php"

	}//End of ATTEMPT TO RETRIEVE ARTICLE
?>

Here is what specifically is happening…

I am okay with Apache taking over in the Level-1 IF statement if there No Slug.

However, for the Level-2 IF statement, I want my PHP code’s Regex to work and my PHP Error Page to fire of someone sent over something like this…

http://local.debbie/articles/SOME_BOGUS_ARTICLE_@@@@@@@@@

I tried changing my .htaccess file to this…


RewriteRule articles/(.+)$ articles/article.php?slug=$1

##RewriteRule articles/([a-zA-Z0-9_-]+)$ articles/article.php?slug=$1

But that doesn’t work, because if the user clicks “Add a Comment”, I take them to…

http://local.debbie/articles/add_comment.php

And the wildcard above tries to do this…

http://local.debbie/articles/article.php?slug=add_comment.php

…which obviously fails.

Then someone suggested I try this…


RewriteCond %{index.php} !-f
RewriteCond %{add_comment.php} !-f
RewriteRule articles/(.+)$ articles/article.php?slug=$1

##RewriteRule articles/([a-zA-Z0-9_-]+)$ articles/article.php?slug=$1

But that isn’t working either?!

I hope you can follow me here?!

Re-stated…

1.) I want to be able to have a Pretty Article URL like this…

http://local.debbie/articles/when-to-hire-a-consultant

2.) But I want my PHP to be able to scrutinize the “slug” for security purposes

3.) I want a pretty Error Page if the URL’s Format is Invalid

4.) I want a pretty Error Page if the Article is Not Found

5.) Whatever I do, needs to also work with a URL like these…

http://local.debbie/articles/add_comment.php

OR

http://local.debbie/articles/add_comment.php?article=52301

AND

http://local.debbie/articles/index.php

Thanks,

Debbie

You’re incredibly close. I think this should do the trick.

# Rewrite only if the request is not pointing to a real file,
# such as add_comment.php or index.php
RewriteCond %{REQUEST_FILENAME} !-f

# Match any kind of slug; PHP will decide if it's valid or not
RewriteRule articles/(.+)$ articles/article.php?slug=$1

That did it!!

(Gee, way to take all of the fun out of struggling!!) :stuck_out_tongue:

Thanks,

Debbie

Jeff,

Okay, I’m not going to let you off that easy… :wink:

Someone told me a week or two ago that relying on Sessions is a bad idea, because it can cause lots of issues with “Tabbed Browsing”. (Honestly, I never fully comprehended what the person was talking about, but it sorta spooked me…) :frowning:

So I am trying to use $_GET more in my code, plus it is good practice for me.

Anyways…

When a (logged in) user is viewing an article like this…

http://local.debbie/articles/postage-meters-can-save-you-money

And he/she decides to add a Comment, I currently rely on…


	$sessMemberID = (isset($_SESSION['sessMemberID']) ? $_SESSION['sessMemberID'] : '');
	$_SESSION['articleID'] = $articleID;

I was hoping to rewrite the link in my code from this…

/articles/add_comment.php

To something like this…

/articles/add_comment.php?article=12345

And then I would still use the $sessmemberID I get from the Session - since if I can’t trust that I’m screwed?!

Questions:

1.) Will the new URL above break the mod_rewrite you gave me?

2.) Is it okay to pass the Article ID in the URL like that?

3.) Would it ever be a security risk to pass the Article ID in the URL?

4.) Not that I would, but wouldn’t passing the Member ID in the URL be a really dangerous thing?? :-/

5.) Again, will using any new script names or query strings related to my “article.php” in the 'article" directory break the new mod_rewrite you provided?

Thanks,

Debbie

:stuck_out_tongue:

I don’t know of any problem like that.

Nope. Apache will still see add_comment.php as the filename and that it’s a real file.

Yup.

Nope, nothing beyond the standard security considerations such as SQL injection and XSS.

Yup. A user might be able to masquerade as someone else by changing the member ID. To protect against that, you’d have to re-authenticate the user using their password on every request. And it would be easier to snoop on users’ viewing habits, since the URL tells you who viewed what page, and URLs are often logged.

New script names, no problem. Query strings… maybe problem. For example, if you visited the URL /articles/postage-meters-can-save-you-money?page=2. You would want to combine the existing query string (page=2) with the substitution query string (slug=$1), and to do that, I think you’d have to add a flag.

RewriteRule articles/(.+)$ articles/article.php?slug=$1 [QSA]

But I haven’t needed to do this in a long time, so I’m not certain that’s how it will work out. You’ll have to try it and see.

No, what I meant was will referencing another script with a query string like this break the mod_rewrite you suggested…

add_comment.php?article=12345

(Instead of using a Session variable, I want to pass the “Article ID” in the URL so my “Add Comment” knows which Article we are adding a Comment to.)

Thanks,

Debbie

Gotcha. That’ll work fine.

Thanks for all of the help!!! :tup:

Debbie