Re: Fwd: Re: question about inter-webapp communication

2011-10-20 Thread Christopher Schultz
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

Garey,
(Thanks for taking this back onto the list).


On 10/19/2011 5:07 PM, Garey Mills wrote:
> Geoserver only has basic authentication on an object by object 
> level. We are deploying it in a unversity that has a Centralized 
> Authentication Server, or CAS. CAS has a implementation that can be
> used in tomcat, and that is realized as a set of filters.

Do you control anything about the implementation of the CAS filters?

> The first problem is that filters have the severe limitation of 
> only allowing one asterisk, making it impossible (as far as I can
> see) to distinguish URLs on the basis of recognizing a pattern in
> the query string.

It's true, filters can only be mapped by relatively simple url-pattern
matching constraints. That doesn't mean the the Filter itself can't be
smart about how it does it's own checks. There is no prohibition on
further processing of the URL to determine how to act. These CAS
filters have to be used in situations where the servlet spec's paltry
url-pattern mapping semantics must be overcome, right? I'm surprised
to hear you say that they are so inflexible.

> So this seems to necessitate recognizing the pattern in code, 
> modifying the URI in some recognizable way (or setting an attribute
> on the request) and redirecting so that it gets intercepted by the
> CAS filter(s).

You can set an attribute on the request and then continue the call
chain (where the CAS filter is later in the chain): there is no need
for a redirect and/or forward to occur.

> This makes it very difficult to work with Geoserver directly. While
>  the code is available, this is a massive project.
> 
> On the other hand, I got my scheme to work more or less, but there
>  are problems. I got it to work by instantiating a
> RequestDispatcher by getNamedDispatcher and finding the servlet
> name ("dispatcher") in Geoserver's web.xml. However, I find that
> the content that Geoserver returns embeds a number of URLs that
> point back to itself. I would have to somehow intercept Geoserver's
> return in my fronting webapp and rewrite those URLs.

If this is the strategy you have chosen, then yes, you will have to
act as a proxy/reverse proxy. You're going to have to do that in any
event. And, it's a total pain in the neck. Better to intercept all the
traffic on it's way to Geoserver and do whatever modifications you
need to on the fly, there, than to try to proxy everything and rewrite
links, etc.

> If I bite the bullet and attempt to change Geoserver, there is 
> another difficulty.

If you can customize Geoserver's behavior by inserting your own
filters somewhere in the filter chain (which is trivial of course),
then I would highly recommend that route. Dual webapps where one of
them does authentication and acts as a re-writing reverse proxy sounds
like madness.

> I am attaching Geoserver's web.xml. Here also are the CAS filters
> from my fronting webapp:
> 
>  CAS Single Sign Out Filter 
> org.jasig.cas.client.session.SingleSignOutFilter
>
> 


Hah. I usually see that called SingleSignOn, but I guess if you want
to get out of everything quickly, that will help, too. :)

> A major problem is how to integrate these two. If you can tell me,
>  maybe I can attempt to introduce the necessary changes to the
> Geoserver servlet.

I didn't see the web.xml from Geoserver, but merging web.xml files
shouldn't be /too/ hard. If you want to keep Geoserver's webapp
relatively untouched (for easier upgrades, etc.) you could use XSLT to
process their original and add your own stuff (for instance,
installing your own filters at the beginning of the filter chain with
all their filters running afterwards).

- -chris
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk6gjYUACgkQ9CaO5/Lv0PBjZQCggQWKntrSt/Ko1tgND8tldEnJ
SWMAniNt+FtWZWqG3M+MwybohZ51w3Mr
=a9sS
-END PGP SIGNATURE-

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Re: Fwd: Re: question about inter-webapp communication

2011-10-19 Thread André Warnier

Garey Mills wrote:



...

Need some time to think about this, but I agree with Christopher that there should be a 
simpler way than what you first outlined.


For a start, have you looked at the urlrewrite filter ?
http://urlrewritefilter.googlecode.com/svn/trunk/src/doc/manual/3.2/index.html

(not thinking of it on its own, but it may already provide part of the needed 
functionality, and since it is a filter, you can stack it with other filters.
For one thing, it can match URL patterns with regexp'es, and it can set request attributes 
in function of such matches.  That makes conditional code in another filter easier to write.)




-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



Fwd: Re: question about inter-webapp communication

2011-10-19 Thread Garey Mills








Christopher -

 Thanks for your reply. I am just going to respond to your first
question here, because it may be that I need to rethink the whole thing.

 /webapp_two is Geoserver, a complex web app that receives requests
for geolocated content and returns it in a number of different formats.
One of the way to distinguish content in Geoserver is to create and add
content to different 'workspaces', each with it's own name. When you
request content from Geoserver, the workspace name appears in the query
string.

 Geoserver only has basic authentication on an object by object
level. We are deploying it in a unversity that has a Centralized
Authentication Server, or CAS. CAS has a implementation that can be used
in tomcat, and that is realized as a set of filters.

 The first problem is that filters have the severe limitation of
only allowing one asterisk, making it impossible (as far as I can see)
to distinguish URLs on the basis of recognizing a pattern in the query
string. So this seems to necessitate recognizing the pattern in code,
modifying the URI in some recognizable way (or setting an attribute on
the request) and redirecting so that it gets intercepted by the CAS
filter(s).

 This makes it very difficult to work with Geoserver directly. While
the code is available, this is a massive project.

 On the other hand, I got my scheme to work more or less, but there
are problems. I got it to work by instantiating a RequestDispatcher by
getNamedDispatcher and finding the servlet name ("dispatcher") in
Geoserver's web.xml. However, I find that the content that Geoserver
returns embeds a number of URLs that point back to itself. I would have
to somehow intercept Geoserver's return in my fronting webapp and
rewrite those URLs.

  If I bite the bullet and attempt to change Geoserver, there is
another difficulty. I am attaching Geoserver's web.xml. Here also are
the CAS filters from my fronting webapp:


CAS Single Sign Out Filter
org.jasig.cas.client.session.SingleSignOutFilter



CAS Authentication Filter
org.jasig.cas.client.authentication.AuthenticationFilter

casServerLoginUrl
https://auth.berkeley.edu/cas/login


serverName
https://linuxdev.lib.berkeley.edu:8443




Ticket Validation Filter
org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter

casServerUrlPrefix
https://auth.berkeley.edu/cas


serverName
https://linuxdev.lib.berkeley.edu:8443




Http Servlet Request Wrapper Filter
org.jasig.cas.client.util.HttpServletRequestWrapperFilter



Assertion Thread Local Filter
org.jasig.cas.client.util.AssertionThreadLocalFilter



CAS Authentication Filter
/PROTECTED/*



Ticket Validation Filter
/PROTECTED/*



Http Servlet Request Wrapper Filter
/PROTECTED/*



Assertion Thread Local Filter
/PROTECTED/*



CAS Single Sign Out Filter
/PROTECTED/*



org.jasig.cas.client.session.SingleSignOutHttpSessionListener



 A major problem is how to integrate these two. If you can tell me,
maybe I can attempt to introduce the necessary changes to the Geoserver
servlet.

Garey Mills

On 10/19/2011 12:33 PM, Christopher Schultz wrote:

 -BEGIN PGP SIGNED MESSAGE-
 Hash: SHA1

 Garey,

 On 10/19/2011 1:56 PM, Garey Mills wrote:

 I want to use /webapp_one as an authentication front end for
 /webapp_two, since /webapp_two is a large, complex web app and I
 want to do authentication filtering on patterns in the query
 string. My scheme is to analyze the request URL in the body of
 /webapp_one. If it should be protected, rewrite it by adding a flag
 into the URI, so that it can be caught by my authentication filter
 in the web.xml, and redirect it back to /webapp_one. If it does not
 have to be protected, or if it has been protected by my filter,
 wrap the request so that it looks like a request to /webapp_two,
 get a   RequestDispatcher from /webapp_two's context, and 'include'
 the output from /webapp_two in the response from /webapp_one.

 That sounds absolutely insane. Can you explain why all this is necessary?


 The problem is that this is not working, and I believe that the
 problem is in how I am getting /webapp_two's ServletContext, or in
 how I am referring to the servlet in /webapp_two's context, since I
 am not seeing any activity from /webapp_two in the logs.

 Here are the particulars:

 * I have 'crossContext=true' set in /webapp_one's context * Here is
 my request wrapper

 public class MyRequestWrapper extends HttpServletRequestWrapper {
 String queryString = null; String uri = null; String contextPath =
 null; String pathTranslated = null;

 public GSRequestWrapper(HttpServletRequest req) { super(req); }

 public void setRequestURI(String newUri) { uri = newUri; } public
 String getRequestURI() { return uri; }

 Since this is a specialized filter, maybe this isn't a big deal, but
 you probably want to call super.getRequestURI() when none has been
 set. Similarly with the other methods.


 public StringBuffer getRequestURL() {

 StringBuffer 

Re: question about inter-webapp communication

2011-10-19 Thread Christopher Schultz
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

Garey,

On 10/19/2011 1:56 PM, Garey Mills wrote:
> I want to use /webapp_one as an authentication front end for 
> /webapp_two, since /webapp_two is a large, complex web app and I
> want to do authentication filtering on patterns in the query
> string. My scheme is to analyze the request URL in the body of
> /webapp_one. If it should be protected, rewrite it by adding a flag
> into the URI, so that it can be caught by my authentication filter
> in the web.xml, and redirect it back to /webapp_one. If it does not
> have to be protected, or if it has been protected by my filter,
> wrap the request so that it looks like a request to /webapp_two,
> get a   RequestDispatcher from /webapp_two's context, and 'include'
> the output from /webapp_two in the response from /webapp_one.

That sounds absolutely insane. Can you explain why all this is necessary?

> The problem is that this is not working, and I believe that the 
> problem is in how I am getting /webapp_two's ServletContext, or in
> how I am referring to the servlet in /webapp_two's context, since I
> am not seeing any activity from /webapp_two in the logs.
> 
> Here are the particulars:
> 
> * I have 'crossContext=true' set in /webapp_one's context * Here is
> my request wrapper
> 
> public class MyRequestWrapper extends HttpServletRequestWrapper { 
> String queryString = null; String uri = null; String contextPath =
> null; String pathTranslated = null;
> 
> public GSRequestWrapper(HttpServletRequest req) { super(req); }
> 
> public void setRequestURI(String newUri) { uri = newUri; } public
> String getRequestURI() { return uri; }

Since this is a specialized filter, maybe this isn't a big deal, but
you probably want to call super.getRequestURI() when none has been
set. Similarly with the other methods.

> public StringBuffer getRequestURL() {
> 
> StringBuffer sb = new StringBuffer(); sb.append(uri + "?" +
> queryString);

Really?

> * Here is the code I use to create the wrapper
> 
> MyRequestWrapper myReq = new MyRequestWrapper(req);
> 
> myReq.setRequestURI(req.getRequestURI().replaceFirst("webapp_one", 
> "webapp_two"));
> 
> myReq.setContextPath(req.getContextPath().replaceFirst("webapp_one",
>
> 
"webapp_two"));
> 
> myReq.setPathTranslated(req.getPathTranslated().replaceFirst("webapp_one",
>
> 
"webapp_two"));
> 
> ServletContext twoContext = sc.getContext("/webapp_two");

What do you do with twoContext after this point?

> * In /webapp_two, the url-pattern intercepted is '/*', so this is
> how I am trying to create the RequestDispatcher
> 
> RequestDispatcher rd = twoContext.getRequestDispatcher("/");

You want to use getRequestDispatcher() with a real path: I would
recommend using the path that you are really trying to reach -- either
the modified one (except that you don't want to have the context-path
in the path because the RequestDispatcher will already know it's bound
to a certain ServletContext) instead of just asking for "/".

Also, I'm not entirely sure what happens to the HttpServletRequest
when you get a request dispatcher using a path and then forward an
existing request. I suspect that the filters and servlets on the other
end see the path you used to fetch the dispatcher, otherwise you could
never forward or include content that didn't match the original URI.

> Trying all this out, I see that the RequestDispatcher I am
> creating is not null, but I am not seeing any activity in
> /webapp_two, and the page returned is blank.

Any error messages in the logs?

> Am I making a mistake in referring to the context of /webapp_two,
> or in how I am creating my request wrapper, or in how I am
> referring to the servlet in /webapp_two?

I think things in general are okay (notwithstanding the very strange
requirements, here) -- there must be some small detail that is
out-of-place.

I would try using the desired path when you fetch a RequestDispatcher
instead of just using "/".

- -chris
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk6fJiAACgkQ9CaO5/Lv0PCEAgCeL+7kPrxL4CPS97kR5+04V+g8
6JMAoLXHVsLq2MceN0cEt6U6sfcrU6d2
=3WPe
-END PGP SIGNATURE-

-
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



question about inter-webapp communication

2011-10-19 Thread Garey Mills

Hello -

Tomcat 7.0.8 on RHEL6. I have two webapps, one accessed at 
/webapp_one and one at /webapp_two. My question has to do with how to 
include output from  /webapp_two in the output of /webapp_one.


I want to use /webapp_one as an authentication front end for 
/webapp_two, since /webapp_two is a large, complex web app and I want to 
do authentication filtering on patterns in the query string. My scheme 
is to analyze the request URL in the body of /webapp_one. If it should 
be protected, rewrite it by adding a flag into the URI, so that it can 
be caught by my authentication filter in the web.xml, and redirect it 
back to /webapp_one. If it does not have to be protected, or if it has 
been protected by my filter, wrap the request so that it looks like a 
request to /webapp_two, get a   RequestDispatcher from /webapp_two's 
context, and 'include' the output from /webapp_two in the response from 
/webapp_one.


The problem is that this is not working, and I believe that the 
problem is in how I am getting /webapp_two's ServletContext, or in how I 
am referring to the servlet in /webapp_two's context, since I am not 
seeing any activity from /webapp_two in the logs.


Here are the particulars:

 * I have 'crossContext=true' set in /webapp_one's context
 * Here is my request wrapper

public class MyRequestWrapper extends HttpServletRequestWrapper {


String queryString = null;
String uri = null;
String contextPath = null;
String pathTranslated = null;

public GSRequestWrapper(HttpServletRequest req) {
super(req);
}

public void setRequestURI(String newUri) { uri = newUri; }
public String getRequestURI() { return uri; }

public void setContextPath(String cp) { contextPath = cp; }
public String getContextPath() { return contextPath; }

public void setPathTranslated(String pt) { pathTranslated = pt; }
public String getPathTranslated() { return pathTranslated; }


public StringBuffer getRequestURL() {

StringBuffer sb = new StringBuffer();
sb.append(uri + "?" + queryString);

   return sb;
}
}

 * Here is the code I use to create the wrapper

MyRequestWrapper myReq = new MyRequestWrapper(req);

myReq.setRequestURI(req.getRequestURI().replaceFirst("webapp_one", 
"webapp_two"));

myReq.setContextPath(req.getContextPath().replaceFirst("webapp_one", 
"webapp_two"));

myReq.setPathTranslated(req.getPathTranslated().replaceFirst("webapp_one", 
"webapp_two"));


ServletContext twoContext = sc.getContext("/webapp_two");


 * In /webapp_two, the url-pattern intercepted is '/*', so this is how
   I am trying to create the RequestDispatcher

RequestDispatcher rd = twoContext.getRequestDispatcher("/");


Trying all this out, I see that the RequestDispatcher I am creating 
is not null, but I am not seeing any activity in /webapp_two, and the 
page returned is blank. Am I making a mistake in referring to the 
context of /webapp_two, or in how I am creating my request wrapper, or 
in how I am referring to the servlet in /webapp_two?


Garey Mills
Library Systems Office
UC Berkeley