• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 450
  • Last Modified:

How to limit MOD_REWRITE to initial request - pass through on redirect ?

Hi All,

Am I using mod_rewrite correctly ?
Or should I be pursuing some other solution ?

* I'd like to provide basic authentication/access control to static pages/files in apache.
* Currently our security/users/ACP etc. are all managed by an application in WebSphere/DB2.  I don't want to duplicate all this information for Apache -- though eventually we will move to LDAP and one central store.

** My hope is to use mod_rewrite (for the short-term to):
1) redirect all URL requests for a certain directory to a servlet;  with the original requested url now appended as a parameter to the servlet:
http://myservlet/?url=http://myOrigURL

2) the servlet checks if the user is logged in (websphere login) -- if not they are redirected to the right forms etc.etc. if successful -- the user is then redirected (response.sendRedirect()) back to the original URL they requested.

3) I figured I could use a condition:
RewriteCond %{REMOTE_ADDR} !localHost

To make sure I'm NOT trapped into an endless URL redirect situation.
However, my servlet response.sendRedirect preserves the original "requesters" IP -- so I can't tell if the request is coming from:
   a) my servlet using a redirect or
   b) directly from an unauthenticated client ?

Servlet - "forward" commands can only forward within the context of the servlet container (i.e. cannot forward to an external URL ?)

My Question:
** Can mod_rewrite work in this situation -- or am I wasting time ??
** Is there some kind of production worthy apache module (currently looking at mod_auth_any) that can help me delegate apache authentication to existing servlet code I have ??

Hope someone can help me out.

Please see rewrite rules I'm using below....


Thanks

Frank

From....MyMOD_REWRITE.conf:
RewriteEngine on
RewriteLog "D:\WebSphere\HTTPServer\logs\rewrite.log"
RewriteLogLevel 4
RewriteCond %{REMMOTE_ADDR} !httpServerHost [OR]
RewriteCond %{REMMOTE_ADDR} !xxx.xxx.xxx.xxx
RewriteRule ^(.*)/download/(.*) http://host/webapp/servlet/forceLoginDirect?urlKey=%{REQUEST_URI}
##NOTE: Tried appending -- but don't really grok the following:
##[R]    and [R,L]
##[PT]  and  [PT,L]
##[P]    and  [P,L]
## Still URL loops endlessly on redirect from sevlet because
##%{REMOTE_ADDR} does not become the httpServerHost IP on redirect.
--------------------------

Note: These rules are specifed at the server level (i.e. NOT directory level)
But they are within context of a VirtualHost:

From....httpd.conf:
<VirtualHost xxx.xxx.xxx.xxx>
      ServerName www.ourdomain.com
      Include E:\WebSphere\HTTPServer\conf\MyMOD_REWRITE.conf
      Alias      /doc                  "E:\WebSphere\App/web/doc"
      etc.etc.
</VirtualHost>


I'd be eternally grateful for ANY feedback/thoughts.

Hope to hear from someone soon.....
Thanks
0
fmisa
Asked:
fmisa
  • 8
  • 7
1 Solution
 
mrielfCommented:
Hi!
I think you shold not redirect back to url in your servlet, instead serve the url content through your servlet if user is authenticated. (or use a regular html page for it)

Use Rewrite like this:

RewriteEngine on

## If the requested url is your servlet, then do nothing
RewriteRule ^/webapp/servlet/forceLoginDirect - [L]

## else do the redirection
RewriteRule ^(.*)/download/(.*) http://host/webapp/servlet/forceLoginDirect?urlKey=%{REQUEST_URI}

0
 
mrielfCommented:
One more thing.

If you want to authenticate at downloads only, yo can use download protector scripts for it with combination rewrite rules (onyl exclude the script from rewriting like the servlet)

And always place the RewriteRule witch do the redirection at the end of rules

0
 
fmisaAuthor Commented:
I'll be a little red faced -- though happy to be on the right track finally -- if what you're saying works.....

The content I need to serve is on the same web server (application server) as my servlet -- but I though in order to "serve" this content (which could be file like pdf, doc etc. not just html) my servlet would have to:
* redirect() -> which get's me back to the endless URL redirect issue...
* forward() -> which I cannot do beyond the servlet's "context" ??
                     (i.e. I can't forward to "http://..." or "../../webapp/" only to "/webapp/.../.."

Am I missing something fundamental here ??

Thanks for replying......

Maybe I'm wrong ?
But I think I'm offering a huge number of points for this ?

Can you please a) supply source code snippet b) comment on other solutions if it turns out that mod_rewrite/servlet approach is not going to be able to work ?

Here's the scenario.....
1) User requests:
http://someHost/headoffice/downloads/someFile.xls

2) Apache mod_rewrite rules - redirect to:
http://someHost/webapp/servlet/forceLoginDirect?
     urlKey=/headoffice/downloads/someFile.xls&
     httpHost=someHost

3) My servlet - checks authentication - if OK - then executes the following:
    String redirectURI = request.getParameter("urlKey");
    String httpHost = request.getParameter("httpHost");    
    response.sendRedirect("http://"+httpHost+redirectURI);

4) Problem is - on redirect %{REMMOTE_ADDR} IP is still that of original "client" -- not my web/ApplicationServer ?
   So the following mod_rewrite condition: RewriteCond %{REMMOTE_ADDR} !httpServerHost
   does NOT prevent the endless URL redirection ??
   Forward is not possible from servlet - I think - beyond the servlets own directory tree/context.....

Hope I'm missing something obvious ??

Thanks for working this question with me....

0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
mrielfCommented:
After authentication check dont redirect to the original page. Redirect it to a dowload script instead.

What kind of Web language you using?

PHP is ok? (I can show you scrips for this in php)
0
 
mrielfCommented:
And what you want? The link is opened in the window or force downlad files?
0
 
fmisaAuthor Commented:
I'm using JSP for scripting.... would you have a JSP example ?
0
 
mrielfCommented:
My idea about to redirect to download script isn't good...
You must integrate two script in one (to prevent security issues)

Look at this component:

http://www.javazoom.net/jzservlets/download4j/download4j.html#overview

I think it will help you out...
0
 
fmisaAuthor Commented:
I will look at this product tonight.
However, I was hoping to let:
   * Apache take care of serving the content.
   * Servlet take care of the authentication
   * and mod_rewrite to switch between the two.....

Completely transparent to the end user.....

If I can't perform this using just apache/module and servlet -- then I'm leaning away from using 3rd party products.  I really don't know how these unknown/untested components will perform in production/load ??

I'm hoping someone here can answer my question definitively......

1) Yes -- this is how mod_rewrite/servlet can do what you want....
2) No -- for these reasons.... it's not possible -- but you could use this approach instead..... hopefully without having to resort to 3rd party products....

I'll consider your thoughts on 2) -- but hope someone here can address 1) for me.....

Talk Soon

Thanks very much
0
 
mrielfCommented:
Sorry I'm not good at JSP programing, but here is the idea:

You must set these headers with response.setHeader:

Cache-Control: private
Pragma: public    
Content-type: application/x-download
Content-Disposition: attachment; filename="FileName"
Accept-Ranges: bytes
Content-Length: FileSize

I found this script (rewriten by me litle). You can rewrite it to your needs:



<?xml version="1.0"?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="1.2">

<jsp:directive.page session="false" import="java.io.*" />
<jsp:scriptlet>
   String p = request.getQueryString();
   boolean ok = true;
   ok = p!=null;
   if (ok) {
      response.setHeader("Content-type","application/x-download");
      response.setHeader("Content-disposition",
         "attachment; filename="+p);
      try {
         int l = (int) new File(p).length();
         response.setContentLength(l);
         byte[] b = new byte[l];
         FileInputStream f = new FileInputStream(p);
         f.read(b);
         ServletOutputStream o = response.getOutputStream();
         o.write(b,0,l);
         o.flush();
         o.close();
         f.close();
      } catch (Exception e) {
         ok = false;
      }
   }
   if (!ok) {
      response.sendError(HttpServletResponse.SC_BAD_REQUEST);
   }
 </jsp:scriptlet>
</jsp:root>
0
 
fmisaAuthor Commented:

Not sure if this going to work - in a scalable manner ?

>> FileInputStream f = new FileInputStream(p);

"p" is the "filename"

But all I've got is the requested URL.....
Apache is already managing the alias mapping//translation to hard-drive for me;  I don't want to do this from my servlet ?

RootDrive:\
                HTTPSeverFolder\
                       htdocs\
                           downloads\
                               MyFile.pdf
                AppServerFolder\
                       App\
                            WEB-INF\
                                 classes\
                                            MyDownloadServlet.class

1) How is my servlet going to "map" URL http://host/download/MyFile.pdf   ==>  drive:\\HTTPServerFolder\htdocs\downloads\MyFile.pdf   ??
     I could have many diffent alias and download directories -- I don't want to manage this meta-data in servlet..... which is why I wanted apache to do the work of download.
     I guess I could use somekind of url/folder naming convention -- but this whole approach is starting to feel like a real hack ? Don't you think.

2) Can the servlet even see/access files outside the scope of it's "context" ..... WEB-INF ??
     I suspect - if I use absolute file path (not relative) - I should be able to open any file on the harddrive -- but then that brings me back to point 1) ??


Am I missing something ?

I had hoped that what I'm looking to do with mod_rewrite/AuthenticationServlet should be easy ??
Surely someone out there has done something similar without have to resort to creating a sort of mini-web/content server in their servlet ??

Any ideas out there ???
0
 
mrielfCommented:
Alternative solution is that not to use rewrite module, instead set apache authentication with alternative authentication module...

Authentication with external CGI or PHP script
http://mod-auth-script.sourceforge.net/

External Authentication Module:
http://unixpapa.com/mod_auth_external.html

Apache authentication module using IBM DB2
http://mod-auth-ibmdb2.sourceforge.net/

0
 
fmisaAuthor Commented:
Thanks for your patience .....

I appreciate your help -- you've got me on the right track......

Please give me another day or two to evaluate -- it's almose working right......
I just want to make sure the code works right before I "accept"


Thanks


Frank
0
 
fmisaAuthor Commented:
Thanks  mrielf......

I really appreciate the help.......
I've accepted -- though I was worried about the overhead of having a servlet serve all the requested "static" content back instead of the HTTP server.
I've tested -- and the extra overhead does not seem to be a big deal ?

** Though I have accepted -- please comment -- one last time on the following........

Though Netscape is working fine -- MSIE is giving me very strange behaviour;  would you be kind enough to comment on the following behaviour:

Everything works fine in the MSIE scenario -- my JSP page is executed -- and when I "print out" values of parameters only the "fileName" is correct.
However, when I actually allow the following code to execute -- it seems the "fileName" is not being set correctly ??

>> response.setHeader("Content-type","application/x-download");
>> response.setHeader("content-disposition","attachment;filename=.....
>> //....etc.etc.
>> File aRequestedFile = ....
>> //.... base my code on your example etc.etc.
>> o.write(b,0,l);
>> o.close();
>> o.flush();

Whenever the requested URL is https://.....   i.e. a long paramter value associated with the key:  ?krypto=kZtbzjcqp.....etc.  
It seems the MSIE file download dialog pops-up -- prompting me to "SAVE"  or "OPEN"  
BUT -- the fileName is NOT the fileName I set in my response header ??
Instead -- it seems to include the a portion of the "krypto" parameter value ??

Any idea what might be confusing MSIE ??
Again -- Netscape seems to be working better.......

Hope to hear from you one last time......

Thanks for your help.....


Frank



0
 
fmisaAuthor Commented:
Also....

FYI

* My research into apache modules:
    a) mod_auth_any
    b) mod_auth_external
    suggests I'd most likely get into scenarios where users would have to authenticate twice.

* Servlet "Filters" I believe -- would give a better solution -- but don't think I can run "Filters" on my current version of WebSpherev.4.x  ??
See:
https://urlrewrite.dev.java.net/
http://publib.boulder.ibm.com/infocenter/wasinfo/index.jsp?topic=/com.ibm.wasee.doc/info/ee/ae/tsec_servlet.html

I'll look into "filters" more carefull later......


Cheers
0
 
mrielfCommented:
Hi!

This is a php example for this problem (i found it on the net):

    $user_agent = strtolower ($_SERVER["HTTP_USER_AGENT"]);
    if ((is_integer (strpos($user_agent, "msie"))) && (is_integer (strpos($user_agent, "win"))))
    {
      header( "Content-Disposition: filename=".basename($filename).";" );
    } else {
      header( "Content-Disposition: attachment; filename=".basename($filename).";" );
    }

From this examle, it seems to me, if client is MSIE, then "attacment; " part must be excluded.

(Sorry for php source. As I said, I'm not expert at jsp programing. Also sorry for my bad english)
0

Featured Post

Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

  • 8
  • 7
Tackle projects and never again get stuck behind a technical roadblock.
Join Now