Keycloak-Tomcat-Adapter: Is there a alternative path for 'keycloak.json'? - java

I try to secure my Java Servlet application with keycloak. All works fine but I don't like the fact that my 'keycloak.json' file is inside my release located. The reason is, if the keycloak definitions are inside my war, so I need for different installations different build processes or the same client credentials on different installations.
My idea was now to place the 'keycloak.json' outside my WEB-INF. Is this possible? Other ideas to solve this problem are also welcome.

if you check the KeycloakOIDCFilter you see there are three additional parameter.
keycloak.config.resolver
keycloak.config.file
keycloak.config.path
We are using file parameter and works like charme.

The Servlet-Filter mentioned above is not necessary.
It is enough to set a context-parameter, like #OkieOth said in his comment.
E.g. set a Parameter like this
<Parameter name="keycloak.config.file" value="MY-PATH/keycloak.json" override="false"/>
within your context (beside the for keycloak configured Valve) or a "context-param" in your web application deployment descriptor (/WEB-INF/web.xml):
<context-param>
<param-name>keycloak.config.file</param-name>
<param-value>MY-PATH/keycloak.json</param-value>
</context-param>
For more Detail about context-params, see The Context Container in section "Context Parameters".

Related

how to add a parameter to spring project before <projectname>/login and after <localhost>:<portnumber> without hardcode?

I'm working on a Spring MVC project. When I run the application the URL is:
http://localhost:8080/insureYou/login
but I want:
http://localhost:8080/contextroot/insureYou/login
Is there any way of doing it without hardcoding?
In a spring-boot project you can set the context-root by specifying the following property in the application.properties file:
server.servlet.context-path=/yourcontextroot
Without spring-boot, it depends on the webserver and Tomcat offers a number of options.
I would personally opt for a META-INF/context.xml file in your war file containing the necessary information but you can also include the information in the server.xml file or in a ROOT.xml file.
See the following links for further guidance:
How to set the context path of a web application in Tomcat 7.0
https://tomcat.apache.org/tomcat-8.0-doc/config/context.html
https://www.baeldung.com/tomcat-root-application
This type of deployment however sometimes is handled separately, through an Apache server reverse-proxy or through URL rewriting.
I recommend you ascertain whether this type of need is already taken care of by your company's deployment procedures, as you may not need to deal with it at all.

Merge servlet parameters from web.xml and container context

We build a webapp using ServletAPI 3 in combination with Tomcat 7 on RHEL.
I try to set a context specific init parameter [getServletConfig().getInitParameter("myinit");] via any of
${CATALINA_HOME}/server.xml (no conf-directory in between but obviuosly the same)
{engine}/{host}/{app}.xml
and to provide some meaningfull default ressource values via webapps war file content "META-INF/context.xml" in parallel.
But as soon as I define a context definition in the XMLs the defined DB connection we provide by context.xml within the war is ignored.
We build the webapp with ant as a single {app}.war file.
Obviously I don't provide the right settings but I don't understand how to do that without moving the db connection settings from META-INF/cotext.xml to the containers context definition (we don't want to do that - though this may obviously be a viable alternative).
Is it possible at all? If so: How? Is there an alternative option to do something similar?
Thanks a lot in advance!

Can I have multiple Java webapps with overlapping paths?

I have a large collection of different independent (stateless) web services written in Java and compiled as WAR files. I want to deploy them to a single web application server.
If the URIs handled by the services in each WAR file began with a prefix I could use as a web app name, then this would be easy. I could, for instance, have
SALES WAR FILE: contains code for the following:
GET http://example.com/sales/widgets
POST http://example.com/sales/widgets
GET http://example.com/sales/sky-hooks
MARKETING WAR FILE: contains code for the following:
GET http://example.com/marketing/widgets
PUT http://example.com/marketing/sky-hooks
...in which case I would simply deploy two WAR files under the names "sales" and "marketing". However, I am not that fortunate. Instead, the URI paths handled by the components overlap. Something like this:
SALES WAR FILE: contains code for the following:
GET http://example.com/widgets/sales
POST http://example.com/widgets/sales
GET http://example.com/sky-hooks/sales
MARKETING WAR FILE: contains code for the following:
GET http://example.com/widgets/marketing
PUT http://example.com/sky-hooks/marketing
My question is how (if at all) I can deploy these on a single web application server.
I am open to suggestions that require a significant amount of work. For instance, my best-so-far idea is to build services that expect a component-name prefix before the regular URI path, then pipe all incoming traffic through a different server that knows what component each URI pattern falls into and modifies the URI to add that prefix. The difficulty with this approach is that tools like Swagger that read my source code will have a mistaken idea of what the URIs look like.
Any ideas?
If you're willing to put apache in front of your web container, you can use apache's mod_proxy to forward request to the right place.
One way this could work, would be deploy the separate wars at separate prefixes as in your first case (sales and marketing) and then use ProxyPass to send the requests to the correct place:
ProxyPass /widget/sales http://example.com/sales/widget
ProxyPass /sky-hooks/sales http://example.com/sales/sky-hooks
ProxyPass /widget/marketing http://example.com/marketing/widget
ProxyPass /sky-hooks/marketing http://example.com/marketing/sky-hooks
Its probably a better idea to just refactor your routing though - it might be hard to maintain.
(EDIT: I originally suggested mod_rewrite, but I wanted to make my answer more specific, and it looks like this could be done purely with proxying)
If I understand your question correctly, one of the solutions would be (I am assuming Tomcat is used but this should apply to most of the modern servlet containers):
1) Deploy your sales and marketing wars with different prefixes. I.e., using your example, they should be able to serve the following urls:
GET http://example.com/sales/widgets/sales
POST http://example.com/sales/widgets/sales
GET http://example.com/sales/sky-hooks/sales
GET http://example.com/marketing/widgets/marketing
PUT http://example.com/marketing/sky-hooks/marketing
2) Use UrlRewriteFilter to craft lightweight web application that will be deployed to your servlet container root prefix (for Tomcat it is called ROOT.war) and will rewrite urls in incoming requests to point to relevant web application.
In other words, incoming request like:
/widgets/sales
will be transformed to:
/sales/widgets/sales
... and delivered to sales webapp.
Similarly, in response urls like:
/sales/widgets/sales
will be rewritten to:
/widgets/sales
3) Deploy this war to root of your servlet container.
This approach is somewhat similar to the one suggested by #nont but does not require apache as a frontend as the rewriting functionality will be handled by root web application (UrlRewriteFilter basically implements mod_rewrite functionality).
In other words you'll be able to deploy all your applications (including this rewrite application that is deployed to the root prefix) to single server alleviating need for extra intermediate proxy/rewrite servers.
First, Determine How the Deployments may be Configured
Are you sure the absolute URIs must overlap? The context root will prefix the path supported by each service, unless the absolute path has somehow been coded into the application itself. The first step is to enable direct access to each WAR file, either through unique context roots or application instances.
Option 1: Set the Context Root for each WAR File Explicitly
The context root for a war file is set at deploy time. For some servers, this can be set outside of the web application using an external deployment descriptor. For Tomcat, it may embedded within META-INF/context.xml. See http://tomcat.apache.org/tomcat-7.0-doc/config/context.html for more information.
Option 2: Separate the Context Root Instances using Multiple Containers
Alternatively, deploy each war file to a separate instance of a Java EE servlet container, each running on a different port. This will solve the deployment conflict in the case of a hard-coded absolute path.
Finally, Set up a Virtual Host and Proxy the Requests via Apache and mod_jk
Once the context roots instances have been made uniquely accessible by one of the previous methods, configure an instance of Apache to serve as a reverse-proxy. First, set up a virtual host to handle requests for the externally visible URI. Next, configure mod_jk to route the requests to the correct WAR file deployment. See http://tomcat.apache.org/connectors-doc/webserver_howto/apache.html for more details.
Afterthoughts
The above solution approach is generic for this type of problem and will require some knowledge of Apache and Tomcat configuration, which were chosen as example reverse-proxy and Java EE servlet technologies for its implementation. Additional detail on the deployment constraints would help to determine an optimal solution. In general, identifying the hard constraints on what may be changed versus what may not be changed should guide you quickly to a solution.
The obvious slotuion is to rename the wars, or refactor so that the appropriate mappings are in the correct place.
Anything else is going to be a bit hacky, you can't change the war name, even to soemthing like below :
SALES WAR FILE: contains code for the following:
GET http://example.com/webapp1/widgets/sales
POST http://example.com/webapp1/widgets/sales
GET http://example.com/webapp1/sky-hooks/sales
MARKETING WAR FILE: contains code for the following:
GET http://example.com/webapp2/widgets/marketing
PUT http://example.com/webapp2/sky-hooks/marketing
You could also create another war for routing/filtering, that redirects everything appropriately - but that also relies on altering url somewhat.
This is a use case for Reverse Proxy. If your web server is Apache, as suggested by #nont proxy_mod can be used to create a reverse proxy.
I know that IBM Http Server (IHS) also allows this mod.

GWT urls change when deployed to tomcat

Simple question, maybe someone knows:
In GWT devmode, my urls look like this: http://myserver/myapp/myservice
When I run 'ant war' and deploy that war on tomcat, they mysteriously change to: http://myserver/myapp/myapp/myservice
Everything still works, but obviously the URLs are uglier. I'd like to just keep the URLs used in devmode. Any info is appreciated, thanks.
-tjw
Deploy the web service as ROOT.war, not as myapp.war, because the first 'myapp' is the web application context path, and 'myapp/myservice' is the path inside the web application.
Change your mappings in your web.xml to all start with / instead of /myapp/ and deploy your application as myapp.war or deploy the war as Root.war
Ok, I've got a solution for this. So many people are having this problem all over the net, I decided to answer my own question. The key is to use #RemoteServiceRelativePath in your RemoteService interface file. For example, to solve my original problem, I would annotate my RemoteService interface like this:
#RemoteServiceRelativePath("../myservice")
This way, whatever path is in front of the service's URL is irrelevant. Now in the web.xml, instead of using /myapp/myservice as the url-pattern, I just use /myservice. Now it works in both GWT's devmode and in Tomcat with no further modification needed.

Java, NetBean : Access web.xml context parameters from Web Service method?

I am new to java so excuse my lame questions:)
I am trying to build a web service in Java NetBeans 6.1 , but I have some troubles with configuration parameters ( like .settings in .net).
What is the right way to save and access such settings in a java web service.
Is there a way to read context parameters from web.xml in a web method?
If no what are the alternatives for storing your configuration variables like pathnames ?
Thank you
Is there a way to read context parameters from web.xml in a web method?
No, this is not easily done using the out-of-the-box. The Web Service system (JAX-WS) has minimal awareness of the Servlet engine (Tomcat). They are designed to be isolated.
If you wanted to use the context parameters, your web service class would need to implement ServletContextListener and retrieve the desired parameters in the initialization parameter (or save the context for later use). Since the Servlet engine and JAX-WS would each have different instances of the object, you'd need to save the values to a static member.
As Lars mentioned, the Properties API or JNDI are your best bets as they're included with Java and are fairly well-known ways to retrieve options. Use Classloader.getResource() to retrieve the Properties in a web context.
If you are using servlets, you can configure parameters in web.xml:
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
</servlet>
These properties will be passed in a ServletConfig object to your servlet's "init" method.
Another way is to read your system's environment variables with
System.getProperty(String name);
But this is not recommended for other than small programs and tests.
There is also the Properties API if you want to use ".properties" files.
http://java.sun.com/javase/6/docs/api/java/util/Properties.html
Finally, I believe looking up configurations with JNDI is pretty common when developing modern web service applications, Netbeans and app containers have pretty good support for that. Google it.
MessageContext ctx = MessageContext.getCurrentThreadsContext();
Servlet wsServlet = (Servlet) ctx.getProperty(HTTPConstants.MC_HTTP_SERVLET);
ServletConfig wsServletConfig = wsServlet.getServletConfig();
ServletContext wsContext = wsServletConfig.getServletContext();
I think the correct answer is ... as always ... "It depends". If you are just running a small implementation with a single server then it depend much on the WS technology you want to use. Some make the servlet context and the context-params easy to access, others don't, in which case accessing properties from a properties file may be easier. Are you going to have an array of servers in a load balanced environment with high traffic where updating the setting for all servers must be instant and centralized in-case of fail-over? If that's the case then do you really want to update the config files for all servers in the farm? How do you synchronize those changes to all those servers? Does it matter to you? If you're storing path-names in a config file then you probably intend to be able to update the path-names to another host in case certain host goes down ("\file_server_host\doc_store" --> "\backup_file_server_host\doc_store") in which case is may actually be better to fail-over using DNS instead. There are too many variables. It really depends on the design; needs; scale of the app.
For simplicity sake, if you just want a simple equivalent of a .settings file then you want a .properties file. Here is an example where I have recently used this in a project: https://github.com/sylnsr/docx4j-ws/blob/master/src/docx4j/TextSubstitution.java

Categories

Resources