I'm running Tomcat 6 to serve several web apps, most of which are public-facing. But I'd like to restrict access to just one webapp, allowing connections only from localhost.
I can restrict access for all webapps using a valve in context.xml, as described in:
Tomcat Restrict access by IP address
But I can't figure out how to restrict access on a per-app basis. Is there a way to do this with my app's web.xml? Or by adding additional rules to context.xml?
Thanks,
-B
Recapping Solution:
$ cp /var/lib/tomcat6/conf/context.xml \
/var/lib/tomcat6/conf/Catalina/localhost/my-app-name.xml
$ cat /var/lib/tomcat6/conf/Catalina/localhost/my-app-name.xml
<Context>
<Valve className="org.apache.catalina.valves.RemoteHostValve" allow="localhost"/>
... {as previously} ...
</Context>
You can create an individual context.xml for you app.
This is an excerpt from Tomcat doc on context configuraion:
Context elements may be explicitly defined:
In the $CATALINA_HOME/conf/context.xml file: the Context element information will be loaded by all webapps.
In the $CATALINA_HOME/conf/[enginename]/[hostname]/context.xml.default file: the Context element information will be loaded by all webapps of that host.
In individual files (with a .xml extension) in the $CATALINA_HOME/conf/[enginename]/[hostname]/ directory. The name of the file (less the .xml) extension will be used as the context path. Multi-level context paths may be defined using #, e.g. foo#bar.xml for a context path of /foo/bar. The default web application may be defined by using a file called ROOT.xml.
Only if a context file does not exist for the application in the $CATALINA_HOME/conf/[enginename]/[hostname]/; in an individual file at /META-INF/context.xml inside the application files. If the web application is packaged as a WAR then /META-INF/context.xml will be copied to $CATALINA_HOME/conf/[enginename]/[hostname]/ and renamed to match the application's context path. Once this file exists, it will not be replaced if a new WAR with a newer /META-INF/context.xml is placed in the host's appBase.
Allowing localhost didn't work for me. I use RemoteAddrValve instead. Keep in mind that some systems use IPv4 addresses (your filter has to match match 127.0.0.1) while others use IPv6 addresses (match the full address, not abbreviated notations like ::1).
<Context>
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="0:0:0:0:0:0:0:1,127\.0\.0\.1" />
</Context>
The attribute allow takes a regexp, so dots need to be escaped. As explained by Dmitry Negoda, this goes in /META-INF/context.xml.
Goto following path: C:\Program Files\Apache Software Foundation\Tomcat 6.0\conf\Catalina\localhost\
Under this path you find " manager.xml " file.
Edit " manager.xml " file,with following content:
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="127.0.0.1,10.100.1.2"/>
<!-- Link to the user database we will get roles from
<ResourceLink name="users" global="UserDatabase"
type="org.apache.catalina.UserDatabase"/>
-->
****** save and run server....You got it.
NOTE : 127.0.0.1 MEANS YOUR SYSTEM IP
10.100.1.2 -THIS IS YOUR FRIEND
Related
I am using Linux Web Apps for Azure together with a SQL Azure Database.
I can save my SQL Azure Database password (for argument's sake, let us say it is pass123) in META-INF/context.xml and this works successfully
<Context>
<Resource name="jdbc/myDB" type="javax.sql.DataSource" auth="Container"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver" initialSize="30"
maxActive="100" validationQuery="SELECT 1"
validationQueryTimeout="1000"
testOnBorrow="true"
url="jdbc:sqlserver://exampleserver.database.windows.net:1433;database=exampledb;encrypt=true;hostNameInCertificate=westeurope1-a.control.database.windows.net;
loginTimeout=10;user=myuser;
password=pass123"
/>
</Context>
I however would like the password to be encrypted and not stored in plaintext in the context.xml file. So I did the following - based on https://learn.microsoft.com/en-us/azure/app-service/containers/configure-language-java#data-sources:
I added two Web App/Configuration/Application Settings
CATALINA_OPTS and THEDBPASSWORD
I set CATALINA_OPTS to be "$CATALINA_OPTS -Ddbpassword={THEDBPASSWORD}"
I set THEDBPASSWORD to be the password of the user
I then changed my context.xml to be password={dbpassword} instead of password=pass123
I then however get the following error in the log (and the application fails to start)
Error: Could not find or load main class "$CATALINA_OPTS -Ddbpassword=pass123" -Ddbpassword=pass123
Any ideas?
I solved it by doing the following:
I had forgotten the $ in context.xml
So context.xml needed to be password=${dbpassword}
I also changed the CATALINA_OPTS to be -Ddbpassword=pass123
I dispensed with the THEDBPASSWORD variable
I am sure this is not the only way or the best way of doing this, but at least it works.
I was partly inspired by Tomcat 8 - context.xml use Environment Variable in Datasource
I have deployed Liferay 6.2 GA4 portal on WebLogic server 10.3.6.0. If the javascript.fast.load property is enabled, the packed javascript version is not got (downloaded) from /combo url. In web browser console the following errors are displayed:
GET https://www.mywebsite.cz/liferay-portal/combo/?browserId=other&minifierType=&languageId=en_US&b=6203&t=1448975784000&/liferay-portal/html/js/aui/color-base/color-base-min.js&/liferay-portal/html/js/aui/event-touch/event-touch-min.js&/liferay-portal/html/js/liferay/dockbar.js 404 (Not Found)
Uncaught TypeError: Cannot read property 'init' of undefined
Due to this for example dockbar doesn't work. From source code it looks like ComboServlet can't get servlet resources found in /combo url parameters. If javascript.fast.load is disabled, portal seems to work.
Weblogic.xml:
<weblogic-web-app
xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.2/weblogic-web-app.xsd"
>
<jsp-descriptor>
<keepgenerated>true</keepgenerated>
<page-check-seconds>60</page-check-seconds>
</jsp-descriptor>
<session-descriptor>
<persistent-store-type>replicated_if_clustered</persistent-store-type>
</session-descriptor>
<container-descriptor>
<prefer-application-packages>
<package-name>antlr.*</package-name>
<package-name>com.ctc.wstx.*</package-name>
<package-name>org.antlr.*</package-name>
<package-name>org.apache.commons.lang.*</package-name>
<package-name>org.mozilla.*</package-name>
<package-name>org.xmlpull.*</package-name>
</prefer-application-packages>
<optimistic-serialization>true</optimistic-serialization>
<show-archived-real-path-enabled>true</show-archived-real-path-enabled>
</container-descriptor>
<context-root>/liferay-portal</context-root>
<library-ref>
<library-name>ext-portal-dependencies</library-name>
<specification-version>1.0</specification-version>
<implementation-version>1.0</implementation-version>
<exact-match>false</exact-match>
</library-ref>
</weblogic-web-app>
Does anybody know what could be the problem? Some WebLogic or Liferay settings? Thanks for any idea or help.
I've had a comparable problem long ago on tomcat when there were problems with the temporary file path - e.g. it growing too long. This might happen in a deeply nested filesystem, or when the total path length is limited.
One of the path-length-limiting factors that I'm aware of is an encrypted home folder on Linux. Also, if the temporary filesystem runs full, the compressed file won't be written and consequently can't be served to the browser.
Check something along those lines, and please report back.
After several days of solving the problem I found the main cause of this problem was this:
Because the customer didn't want to have portal dependencies (portal-service.jar, portlet-api.jar, ...) as domain libraries, I deployed it as Java EE Shared Libraries. Obviously it works differently than I expected. So after persuasion of customer, I put liferay dependencies to domain lib folder and suddenly everything started to work.
I am having trouble with configuring a webapp in Tomcat 7. In my WAR file, there is a properties file myApp/WEB-INF/classes/myProps.props, and it contains environment-specific properites. I am trying to override that configuration file on the server, so that the same WAR file will deploy to multiple environments.
I heard there was a way to do this using replacement config files in tomcat/conf/Catalina/myApp. This is the method I am having trouble figuring out.
Also, myApp.war is one of many running on the same Tomcat server, and it does not run as localhost. I want to be able to solve this problem for several of the webapps.
Server version: Apache Tomcat/7.0.23
Server built: Nov 20 2011 07:36:25
Server number: 7.0.23.0
OS Name: Linux
Your tomcat/conf/Catalina/<host> can contain context descriptors that let you configure lots of things including defining "environment entries", which are accessible from Java via JNDI. There are lots of ways to go about using it. Personally, I set an environment entry which is the file system path to my properties file. My app is built to check for this entry, and if it doesn't exist, look for the file on the classpath instead. That way, in dev, we have the dev properties right there on the classpath, but when we build and deploy, we point it to an external file.
There's good documentation for configuring a context on the Tomcat website. See the Defining a Context section on details of how to create the file and where to put it.
As an example, if your host is named myHost and your app is a war file named myApp.war in the webapps directory, then you could create tomcat/conf/Catalina/myHost/myApp.xml with this content:
<Context>
<Environment name="configurationPath" value="/home/tomcat/myApp.properties" type="java.lang.String"/>
</Context>
Then from your code, you'd do a JNDI lookup on java:comp/env/configurationPath (95% certainty here) to get that string value.
I like .properties files instead of
JNDI - why build complex object during program configuration instead of initialization time?
system properties - you can't separately configure several instances of same WAR in single Tomcat
context parameters - they accessible only in javax.servlet.Filter, javax.servlet.ServletContextListener which my be inconvenient
Tomcat 7 Context hold Loader element. According to docs deployment descriptor (what in <Context> tag) can be placed in:
$CATALINA_BASE/conf/server.xml - bad - require server restarts in order to reread config
$CATALINA_BASE/conf/context.xml - bad - shared across all applications
$CATALINA_BASE/work/$APP.war:/META-INF/context.xml - bad - require repackaging in order to change config
$CATALINA_BASE/work/[enginename]/[hostname]/$APP/META-INF/context.xml - nice, but see last option!!
$CATALINA_BASE/webapps/$APP/META-INF/context.xml - nice, but see last option!!
$CATALINA_BASE/conf/[enginename]/[hostname]/$APP.xml - best - completely out of application and automatically scanned for changes!!!
Context can hold custom Loader org.apache.catalina.loader.VirtualWebappLoader (available in modern Tomcat 7, you can add own separate classpath to your .properties), and Parameter (accessed via FilterConfig.getServletContext().getInitParameter(name)) and Environment (accessed via new InitialContext().lookup("java:comp/env").lookup("name")):
<Context docBase="${basedir}/src/main/webapp"
reloadable="true">
<!-- http://tomcat.apache.org/tomcat-7.0-doc/config/context.html -->
<Resources className="org.apache.naming.resources.VirtualDirContext"
extraResourcePaths="/WEB-INF/classes=${basedir}/target/classes,/WEB-INF/lib=${basedir}/target/${project.build.finalName}/WEB-INF/lib"/>
<Loader className="org.apache.catalina.loader.VirtualWebappLoader"
virtualClasspath="${basedir}/target/classes;${basedir}/target/${project.build.finalName}/WEB-INF/lib"/>
<JarScanner scanAllDirectories="true"/>
<Parameter name="min" value="dev"/>
<Environment name="app.devel.ldap" value="USER" type="java.lang.String" override="true"/>
<Environment name="app.devel.permitAll" value="true" type="java.lang.String" override="true"/>
</Context>
If you use Spring and it's XML config:
<context:property-placeholder location="classpath:app.properties"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:#${db.host}:${db.port}:${db.user}"/>
<property name="username" value="${db.user}"/>
<property name="password" value="${db.pass}"/>
</bean>
With Spring injecting above properties into bean fields are easy:
#Value("${db.user}") String defaultSchema;
instead of JNDI:
#Inject ApplicationContext context;
Enviroment env = context.getEnvironment();
String defaultSchema = env.getProperty("db.user");
Note also that EL allow this (default values and deep recursive substitution):
#Value('${db.user:testdb}') private String dbUserName;
<property name='username' value='${db.user.${env}}'/>
See also:
Adding a directory to tomcat classpath
Can I create a custom classpath on a per application basis in Tomcat
How to read a properties file outside my webapp context in Tomcat
Configure Tomcat to use properties file to load DB connection information
Should you set up database connection properties in server.xml or context.xml
Externalize Tomcat configuration
NOTE With extending classpath to live directory you also allowed to externilize any other configs, like logging, auth, atc. I externilize logback.xmlin such way.
UPDATE Tomcat 8 change syntax for <Resources> and <Loader> elements, corresponding part now look like:
<Resources>
<PostResources className="org.apache.catalina.webresources.DirResourceSet"
webAppMount="/WEB-INF/classes" base="${basedir}/target/classes" />
<PostResources className="org.apache.catalina.webresources.DirResourceSet"
webAppMount="/WEB-INF/lib" base="${basedir}/target/${project.build.finalName}/WEB-INF/lib" />
</Resources>
You can try to place your configuration (properties file) in Apache Tomcat\lib in JAR file and remove it from the web application. When the Tomcat's class loader won't find your config in webapp it will try to find in "lib" directory. So you can externalize your configuration just moving the config to global lib dir (it's shared among other webapps).
I just added a setenv.bat or setenv.sh script in the bin folder of tomcat. Set the classpath variable like
set CLASSPATH=my-propery-folder
Can I supposed to launch One-Jar using JWS? One-JAR provides custom classloader that knows how to load classes and resources from a jars inside an archive whereas in JWS we need to specify each JAR that is being used in resources.
What I supposed to specify in JNLP if I am trying to launch One-Jar -
<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.0+" codebase="" href="">
<information>
<title>Application</title>
<vendor>ABC</vendor>
</information>
<resources>
<!-- Application Resources -->
<j2se version="1.5+"
href="http://java.sun.com/products/autodl/j2se"/>
<jar href="Application.jar" main="true" download="eager" />
</resources>
<application-desc main-class="com.simontuffs.onejar.Boot">
</application-desc>
<update check="background"/>
<security>
<all-permissions/>
</security>
</jnlp>
My Application JAR that is One-JAR contains -
com\simontuffs\onejar\<contains complied classes> like JarClassLoader$1.class etc
lib/<contains all jar>
OneJar.class
main/<my application's jar>
META-INF\MANIFEST.MF\ <contains >
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.1
Created-By: One-Jar 0.96 Ant taskdef
Main-Class: com.simontuffs.onejar.Boot
One-Jar-Main-Class: com.application.main.Entry
Name: com/simontuffs/onejar/Boot$3.class
SHA1-Digest: +LPrezs+UEFcE3J7QvumcAEO8Z0=
Name: OneJar.class
SHA1-Digest: 28pzzJWqEpLk1xFwJ/jsAav8LyI=
Name: lib/commons-io-1.4.jar
SHA1-Digest: qHYtB+ds/eI5Ulel2ke6fB29Pc4=
etc..etc..
How to specify these com/simontuffs/onejar/Boot$3.class paths in resource ?
Part of the problem of supporting tools like One-Jar is that loading Jars within Jars requires a custom class-loader. By default JWS will use the usual JRE class-loaders - which do not support it.
There are two possible ways that you might get around that (that I know of).
1. Get access to the custom class-loader.
Get an instance of the custom loader used by One-Jar and set it as the context class-loader. This would require a trusted app., but I get the impression that your app. is trusted.
I have no idea if the One-Jar API provides this loader for your own app.'s use.
2. Use some options when building.
From Options and VM Properties..
one-jar.jar.names
true: Recorded classes are kept in directories corresponding to their jar names.
false: Recorded classes are flattened into a single directory.
Duplicates are ignored (first wins)
The 2nd option sounds like a standard 'fat jar'. That should work with the conventional (default) class-loader used by JWS.
I am using log4net during my development, as as part of a project constraint, I now need to add it to the Global Assembly Cache.
The logging definitions are in a file Log4Net.xml. That file is referenced in my assemblyinfo as: [assembly: log4net.Config.XmlConfigurator(ConfigFile = "Log4Net.xml", Watch = true)]. So long as the xml file was in the same directory as the log4net.dll, everything has been working fine.
However now that I've added log4net to the GAC, it is no longer picking up the xml file.
Does anyone know what I need to change in order to have it pick up the XML file again? Is hardcoding the patch in the assembly reference the only way?
Many thanks
log4net expects the config file to be in the path returned by:
System.AppDomain.CurrentDomain.BaseDirectory
Let your application print this information to some file and then you know where you need to place the config file.
Of course there are other solutions, but then you cannot use the attribute anymore. Calling the ConfigureAndWatch() method directly allows you to figure out yourself where the config file is; you can even decide on a location (does not have to be a hard-coded path).
You might ensure that your log4net.xml file is set to "Copy Always" (Right Click on log4net.xml -> Properties -> Copy to Output Directory = Copy always). To ensure that your config file is being copied, you should check your bin\debug or bin\release directory and verify that the log4net.xml file exists in the same directory that your application executes.
If that doesn't workthen you can try enabling internal debugging in log4net. To enable internal debugging, add the following key to your app.config file. This will send internal log4net debug messages to your Visual Studio Output window (View -> Output).
<configuration>
<appSettings>
<add key="log4net.Internal.Debug" value="true"/>
</appSettings>
</configuration>
For more information on log4net's internal debugging, you might check Phil Haack's blog post here.
If all else fails, you can turn on internal debugging and explicitly load the configuration by calling log4net's XmlConfigurator.ConfigureAndWatch method.
var fi = new FileInfo(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\log4net.xml");
XmlConfigurator.ConfigureAndWatch(fi);