Proxy pass fails with Spring secuity - apache

i have written set of rules to redirect
http://server.com/application/c/<UserIdValue>
type of url's to
http://localserver.com/application/?userid=<UserIdValue>
i wrote the following rules in apache httpd.conf
<Location /application>
ProxyPassReverse http://server.com/application/
RewriteEngine On
RewriteCond %{REQUEST_URI} /c/ [NC]
RewriteRule application/c/(.*)$ http://localserver.com/application/?userid=$1 [QSA,P]
With this i can access login page and other pages in my application, but when i try to login/logout in application , it break into 'localserver' location .
the problem is with spring security j_spring_security_check, j_spring_security_logout. i dont have any clue what to do for this.
Spring security is taking precedence over proxy pass!!!!!

There are two things you will have to change to get this to work:
Change your ProxyPass / ProxyPassReverse lines to not end with a trailing /.
Tell your Application Server to set the contextURL correctly (ProxyPassReverse won't change URIs on forms for you). If you are using Tomcat, you do this by editing conf/server.xml, finding the tag that has the attribute protocol="HTTP/1.1" on it, and adding two new attributes: proxyHost="localserver.com" proxyPort="80" (you don't strictly need the proxyPort="80" if localserver.com and server.com are running on the same port).
The cause of problem 1 is that Spring Security doesn't normalise URIs, so if the proxy gives your application server a URI like http://server.com/application//j_spring_security_check, the Spring Security interceptor will match it against http://server.com/application/j_spring_security_check, note that it is different due to the extra slash, and refuse to intercept the request.

Related

Apache Conditional Redirect Rule not forwarding header values

Goal:
To perform conditional redirect/forward from Site1 to Site2 based on specific header (HTTP_SM_USER) value of the request (in Site1) and ensure all the current custom header data is forwarded as part of the redirect/forward to Site2. The user can see the url change in the browser window after the redirect.
Flow:
User accesses Site 1 --> External Application Sets few custom headers in addition to default HTTP headers based on certain criteria --> Web-server looks for specific header value and if matches redirect all the headers to Site 2.
Apache Web server Config:
<VirtualHost *.443>
ServerName site1.com
ServerAdmin ashish#test.com
UseCanonicalName on
DocumentRoot /var/www/html
#
# SSL Config comes here
#
ErrorLog /path/to/error/log
TransferLog /path/to/access/log
LogLevel warn
RewriteEngine On
RewriteCond %{HTTP:SM_USER} ^USER1$ [NC]
RewriteRule .* https://site2.com/$1 [R=301, L]
<Location /page1>
.
.
</Location>
.
.
.
</VirtualHost>
Question: The Conditional Redirect happens but the headers are lost. What should I do to ensure the HTTP headers are forwarded as well ? I tried to see into apache mod_proxy but wasn't sure how in this scenario to use it. Experts please help. Any alternative suggestions are welcome too.
Solution:
I finally got it to work (with mod_proxy) after a lot of troubleshooting using the below flags and proxy rules. All Rewrite rules were removed.
ProxyRequests Off
ProxyPreserveHost On
SSLProxyEngine On
ProxyPass "/" "https://site2.com/" Keepalive=On
ProxyPassReverse "/" "https://site2.com/"
Note: User accesses Site 1 -> External app sets headers and apache immediately proxies to Site 2. Headers are now available on Site2.
You can't have the redirect "forward" headers, because it is up to the client what it sends to the next server after it has been issued a redirect. It may choose not to follow the redirect at all! Unlikely but just to make it clear what the situation is.
If you want the URL to change in the browser, then you need to do this on the application side. Have your application handle directing to the next server, and just issue a 200 response with an instruction for it to do so. Then it can send the custom headers as it did with the first request.
If that is not acceptable, then using mod_proxy could work as you said, but it would not change the URL in the browser, because the first server would be proxying the request to the second, so the browser would still see it as being the first.
In summary, you cannot do what you want to do, because HTTP does not work that way, so you are going to have to compromise in some way, either by not changing the URL in the browser, or by updating the application to take care of it.

reverse proxy with SSL and url encoding, path change

environment http://etrafficcontrol.com/misc/proxy.png
I have two applications. One is an e-commerce site (Drupal 7 running on LAMP) hosted on AWS, and the other is the checkout system which is ASP on IIS-6, is located inside our company, and requires SSL.
Currently we put up with the situation where our customers get forwarded to another domain for checkout -- kind of like what happens with ebay and PayPal. But this leads to difficulty with site tracking code, and kind of feels wrong for the shopper to get forwarded off of the e-commerce site for checkout.
The main concern is that we use Google campaigns, so we want to track conversions from advertising to, and rich content on, domain-1, but the actual sale happens at the time of checkout on domain-2.
Rather than send visitors from www.domain1.com/cart to domain2.com/miscX, I've tried to setup ProxyPass and ProxyPassReverse so I can send them to www.domain1.com/shop/miscX.
App1 (drupal) is in domain1.com/*, and the .htaccess stuff bypasses Drupal's design to intercept everything. The "misc" paths come from the fact that I'm redirecting into a subdirectory, and then proxying from there. When the proxied pages render, they have some hard-coded paths to /miscX, and without making special provisions for those during the rediects, I wind up with /miscX/ (instead of /shop/miscX/ which will follow the proxy) and that causes missing css, js, etc.
Note: Our business customers can login directly to domain2.com, so I'd like to keep that portal unchanged.
Below, local-d7 is a local test instance of the domain1 server. A test of the proxy shows that this concept works, with SSL.
I have this almost working, but it seems like URL-encoded parameters are being lost (even though query strings are ok). When I introduce the proxy, server2 doesn't appear see encoded params (it's a specialized app and I don't know how to view what IIS is receiving). When I route the domain2 test portal login thru apache on server-1 in such a way that doesn't have encoded params, the login works.
In effect I'm trying to
reverse proxy
change path (put an app running in / on domain-2 and expose into a subdir "/shop" on Domain-1
support SSL
proxy an IIS server behind Apache
try to not modify the IIS server so that it can continue to be used by it's original domain-2.com URL, and
do this on a hosted server where I [may] have limited configuration control of Apache. (currently testing on XAMPP).
I've tried all sorts of things in addition to what's shown here, including rewriterules, redirects, etc. I'm just not experienced at all at mod_proxy or mod_rewrite, etc. But it seems to me that this arrangement of a proxy should be doable with some amount of work and possibly fixing server SSL certificates.
Advice? --Thanks
vhosts.conf
## Redirect /misc1/ https://local-d7/shop/misc1/
## Redirect /misc2/ https://local-d7/shop/misc2/
## Redirect /misc3/ https://local-d7/shop/misc3/
## ProxyRequests Off
## ProxyPreserveHost On
## RequestHeader set Proxy-SSL true
## ProxyPass /shop/ https://www.shop.com/
## ProxyPassReverse /shop/ https://www.shop.com/
ProxyPass /shop/ https://www.domain2.com/
ProxyPassReverse /shop/ https://www.domain2.com/
ProxyPass /misc1/ https://www.domain2.com/misc1/
ProxyPassReverse /misc1/ https://www.domain2.com/misc1/
ProxyPass /misc2/ https://www.domain2.com/misc2/
ProxyPassReverse /misc2/ https://www.domain2.com/misc2/
ProxyPass /misc3/ https://www.domain2.com/misc3/
ProxyPassReverse /misc3/ https://www.domain2.com/misc3/
.htaccess
RewriteCond %{REQUEST_URI} ^/misc1/
RewriteCond %{REQUEST_URI} ^/misc2/
RewriteCond %{REQUEST_URI} ^/misc3/
RewriteRule (.*) /shop/$1

How to correct (Wicket in) Tomcat at /myapp behinds Apache proxy at / that send incorrect redirect to /myapp/xxx instead of /xxx?

I have deployed my Wicket app at /myapp in Tomcat, and I have put it behind Apache web server using
ProxyPass / http://localhost:8080/myapp/
ProxyPassReverse / http://localhost:8080/myapp/
Now Wicket incorrectly redirect users to /myapp/xxx instead of /xxx.
Is there any way to make Wicket(1.3.5) use / as my root path (instead of /myapp which is servlet deployment context path)?!
Edit: There is a solution described at following link but it doesn't works for 1.3.5 version:
I found it: https://cwiki.apache.org/WICKET/wicket-behind-a-front-end-proxy.html
Edit: The problem is that wicket uses relative path redirects with ServletResponse#sendRedirect and Tomcat convert them to absolutes redirects containing /myapp at beginning. I have tried mod_jk(AJP) but there was no difference!
There should be some way to tell proxy-pass or mod-jk to rewrite redirects before sending them to client!
I didn't find direct answer but used following workaround with mod jk, I guess it is also possible to do with proxy pass.
RewriteRule /myapp/(.*) /$1 [L,R]
RewriteRule ^(.*) /myapp$1 [PT]
JkMount /myapp/* ajp13_worker
First line redirects request coming from client starting with /myapp/* (which are result of incorrect Wicket/Tomcat/Apache redirects) to /*.
Second line rewrites all requests from /* to /myapp/* and third line send them to tomcat.
For proxy pass, third line should be replaced with:
ProxyPass /myapp/ http://localhost:8080/myapp/
ProxyPassReverse /myapp/ http://localhost:8080/myapp/
You may find this Tomcat document helpful:
http://tomcat.apache.org/connectors-doc/generic_howto/proxy.html
It addresses the above situation with RedirectMatch and mod_rewrite.
Not tested myself, but have you looked at mod_rewrite? There are some examples describing what you want to do here.

Reverse Proxy in CakePHP?

I've got a CakePHP application, and the following directives in my httpd.conf
ProxyRequests off
ProxyPass /forum/ http://somesite.com/phpbb3
ProxyPass /gallery/ http://someothersite.com/gallery3
<Location /forum/>
ProxyPassReverse /
</Location>
<Location /gallery/>
ProxyPassReverse /
</Location>
Without CakePHP this works fine - but because CakePHP is using it's own redirection logic from routes.php and other sources, it seems to override any proxy settings, so any call to "/community" on my server follows the default pathway of looking for a Controller called CommunityController.
My issue here is that I want to have one server that serves muliple applications, but keep it seamless to the user - so a complete PHPBB application can for instance run within the "/forum" directory as if it were a controller in CakePHP.
Has anyone done this before, and can it be done? Why does mod_rewrite and/or the routes.php file override my mod_proxy directives??
Perhaps instead of using mod_proxy, you could use mod_rewrite to create a RewriteRule directive with the [P] (proxy) flag in conjunction with the [L] (last rule) flag.
'proxy|P' (force proxy):
This flag
forces the substitution part to be
internally sent as a proxy request and
immediately (rewrite processing stops
here) put through the proxy module.
You must make sure that the
substitution string is a valid URI
(typically starting with
http://hostname) which can be handled
by the Apache proxy module. If not,
you will get an error from the proxy
module. Use this flag to achieve a
more powerful implementation of the
ProxyPass directive, to map remote
content into the namespace of the
local server.
Note: mod_proxy must be enabled in
order to use this flag.
'last|L' (last rule):
Stop the
rewriting process here and don't apply
any more rewrite rules. This
corresponds to the Perl last command
or the break command in C. Use this
flag to prevent the currently
rewritten URL from being rewritten
further by following rules. For
example, use it to rewrite the
root-path URL ('/') to a real one,
e.g., '/e/www/'.

Apache - Reverse Proxy and HTTP 302 status message

My team is trying to setup an Apache reverse proxy from a customer's site into one of our web applications.
http://www.example.com/app1/some-path maps to http://internal1.example.com/some-path
Inside our application we use struts and have redirect = true set on certain actions in order to provide certain functionality. The 302 status messages from these re-directs cause the user to break out of the proxy resulting in an error page for the end user.
HTTP/1.1 302 Found
Location: http://internal.example.com/some-path/redirect
Is there any way to setup the reverse proxy in apache so that the redirects work correctly?
http://www.example.com/app1/some-path/redirect
There is an article titled Running a Reverse Proxy in Apache that seems to address your problem. It even uses the same example.com and /app1 that you have in your example. Go to the "Configuring the Proxy" section for examples on how to use ProxyPassReverse.
The AskApache article is quite helpful, but in practice I found a combination of Rewrite rules and ProxyPassReverse to be more flexible. So in your case I'd do something like this:
<VirtualHost example>
ServerName www.example.com
ProxyPassReverse /app1/some-path/ http://internal1.example.com/some-path/
RewriteEngine On
RewriteRule /app1/(.*) http://internal1.example.com/some-path$1 [P]
...
</VirtualHost>
I like this better because it gives you finer-grained control over the paths you're proxying for the internal server. In our case we wanted to expose only part of third-party application. Note that this doesn't address hard-coded links in HTML, which the AskApache article covers.
Also, note that you can have multiple ProxyPassReverse lines:
ProxyPassReverse / http://internal1.example.com/some-path
ProxyPassReverse / http://internal2.example.com/some-path
I mention this only because another third-party app we were proxying was sending out redirects that didn't include their internal host name, just a different port.
As a final note, keep in mind that Firebug is extremely useful when debugging the redirects.
Basically, ProxyPassReverse should take care of rewriting the Location header for you, as Kevin Hakanson pointed out.
One pitfall I have encountered is missing the trailing slash in the url argument. Make sure to use:
ProxyPassReverse / http://internal1.example.com/some-path/
(note the trailing slash!)
Try using the AJP connector instead of reverse proxy. Certainly not a trivial change, but I've found that a lot of the URL nightmares go away when using AJP instead of reverse proxy.