Tomcat 7 - Secure a folder under webapps folder - security

My web application is 'myweb', within this web app my code refers '123.pdf' under 'files' folder like http://localhost:8080/files/123.pdf
webapps
|
|--myweb
|
|--files
|
|--123.pdf
I want the resource (123.pdf) available only for logged in users, when I try to access directly by pasting (http://localhost:8080/files/123.pdf) in the browser address bar, without logging into the portal, I could access the file.
Basically I want to secure the 'files' folder under 'webapps', so that only authenticated users in portal could access resources under 'files' folder. How can I achieve this?

I found a way to solve this problem. This is what I came up with,
1) Convert 'files' folder to a web application and make files (say pdf) secured by using tomcat's
FORM based authentication
2) After getting authenticated to 'myweb' - here authentication is not tomcat container based, its based on
spring & hibernate -
asynchronously invoke a servlet (PopulateServlet.java) in 'files' web app from '/myweb/customerhomepage.jsp' and set tomcat role username & pwd in 'files' web app session
whenever there is a request to protected pdf under 'files' web app, login.jsp will be invoked - in this jsp populate hidden j_username & j_password fields
from session object which was already populated by PopulateServlet. Using jquery ajax, the html form will be submitted to tomcat
for resource authentication.
'files' web app changes:
Create new role and user name and password
/conf/tomcat-users.xml
<role rolename="tomcat"/>
<user username="tomcat" password="tomcat" roles="tomcat"/>
Create WEB-INF/web.xml
<servlet>
<servlet-name>Populate</servlet-name>
<servlet-class>PopulateServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Populate</servlet-name>
<url-pattern>/Populate</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Logout</servlet-name>
<servlet-class>LogOutServlet</servlet-class> <!-- in this servlet, call session.invalidate() -->
</servlet>
<servlet-mapping>
<servlet-name>Logout</servlet-name>
<url-pattern>/Logout</url-pattern>
</servlet-mapping>
<security-constraint>
<display-name>Security Constraint</display-name>
<web-resource-collection>
<web-resource-name>Protected Area</web-resource-name>
<url-pattern>/jsp/security/protected/*</url-pattern>
<url-pattern>*.pdf</url-pattern>
<http-method>DELETE</http-method>
<http-method>GET</http-method>
<http-method>POST</http-method>
<http-method>PUT</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>tomcat</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>Form-Based Authentication Area</realm-name>
<form-login-config>
<form-login-page>/jsp/security/protected/login.jsp</form-login-page>
<form-error-page>/jsp/security/protected/error.jsp</form-error-page>
</form-login-config>
</login-config>
<!-- Security roles referenced by this web application -->
<security-role>
<role-name>tomcat</role-name>
</security-role>
Create login.jsp and error.jsp under /files/jsp/security/protected/
login.jsp
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$("#secure").submit();
});
</script>
...
<form method="POST" action='<%= response.encodeURL("j_security_check") %>' name="secure" id="secure">
<input type="hidden" name="j_username" value='<%=session.getAttribute("j_username")%>' />
<input type="hidden" name="j_password" value='<%=session.getAttribute("j_password")%>' />
</form>
...
PopulateServlet.java
HttpSession session = request.getSession(true);
session.setAttribute("j_username","tomcat");
session.setAttribute("j_password","tomcat");
'myweb' web app changes:
customerhomepage.jsp
$.get('/files/Populate?ts='+new Date().getMilliseconds());

Just add another configuration in your spring web config:
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("reports/**")
.addResourceLocations(reportsRootPath);
}
reportsRootPath is defined in properties file which could be any file System location.
Files are accessible like; reports/myReport.pdf
Here is the documentation which guided me

Related

tomcat 7 Form based authentification

given a Servlet HelloServlet:
#WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* Default constructor.
*/
public HelloServlet() {
// TODO Auto-generated constructor stub
}
#Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.print("hello my Friend: " + request.getRemoteUser());
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("This is the Test Servlet");
Enumeration headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = (String) headerNames.nextElement();
out.print("<br/>Header Name: <em>" + headerName);
String headerValue = request.getHeader(headerName);
out.print("</em>, Header Value: <em>" + headerValue);
out.println("</em>");
}
}
....
}
with a declared tomcat security policy in web.xml:
<security-constraint>
<web-resource-collection>
<web-resource-name>my application</web-resource-name>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>tomcat</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/login-failed.jsp</form-error-page>
</form-login-config>
</login-config>
and tomcat-roles definitions in conf/tomcat-users.xml
<role rolename="tomcat"/>
<role rolename="role1"/>
<user username="tomcat" password="tomcat" roles="tomcat"/>
<user username="both" password="tomcat" roles="tomcat,role1"/>
<user username="role1" password="tomcat" roles="role1"/>
the realm in "server.xml" is:
<Realm className="org.apache.catalina.realm.LockOutRealm">
<!-- This Realm uses the UserDatabase configured in the global JNDI
resources under the key "UserDatabase". Any edits
that are performed against this UserDatabase are immediately
available for use by the Realm. -->
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
,I tried to access the Servlet "HelloServlet" with url localhost/jsfWorkgroup/HelloServlet.
like expected, I am (re)directed to the login-page:
<form method="POST" action="j_security_check">
<table>
<tr>
<td colspan="2">Login to the Tomcat-Demo application:</td>
</tr>
<tr>
<td>Name:</td>
<td><input type="text" name="j_username" /></td>
</tr>
<tr>
<td>Password:</td>
<td><input type="password" name="j_password"/ ></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="Go" /></td>
</tr>
</table>
</form>
No matter which id-Token I used:
username:tomcat passwort:tomcat
username:both passwort:tomcat
I still come to the failure /login-failed.jsp.
here is my take on this: tomcat acts on redirect me to the to login page, but does not read the conf/tomcat-users.xml to valid my login(even after several reboots).
what do you think about it ?
configuration: Tomcat 7.0.23, Eclipse-Indigo
following to proposition of #pd40 I tried the examples/jsp/security/protected/ examples but not in the Eclipse IDE where Tomcat is usually embedded along with the other servers (Glassfish, JBoss, ect..) , rather I started the tomcat server as standalone (in its /bin directory) .. and there it works.
but when it's attemped to run security based Web-application in Tomcat within Eclipse, it failed again, even using the configuration described above.
I don't know if I am right but Web-Application Security is only supported when tomcat runs outside of eclipse..
The tomcat example web.xml includes the following section below <login-config>:
<!-- Security roles referenced by this web application -->
<security-role>
<role-name>role1</role-name>
</security-role>
<security-role>
<role-name>tomcat</role-name>
</security-role>
which you may need.
Tomcat includes an example war which contains an auth using tomcat-users.xml similar to what you are trying. If tomcat home/webapps/examples is deployed try accessing http://localhost/examples/jsp/security/protected/. Make sure the XML comments around the role/user section of tomcat-users.xml have been removed. They are commented out by default.
<!-- Un comment me
<role rolename="tomcat"/>
<role rolename="role1"/>
<user username="tomcat" password="tomcat" roles="tomcat"/>
<user username="both" password="tomcat" roles="tomcat,role1"/>
<user username="role1" password="tomcat" roles="role1"/>
-->
You can consider bumping up the logging to help diagnose the auth issue.
This is too late for me to answer but maybe someone coming here may find this useful.
Actually if you are facing the problem of not getting the tomcat configuration to work through eclipse and running outside it, then just delete the server from eclipse servers tab and add again. This should solve the problem.
You have restricted access to your content by
defining secured pages in web.xml:
<url-pattern>/*</url-pattern>
that wildcard is refering to all pages in content path.
So you obtain an infinitive loop of redirections to login page.
I discovered that if you change the configuration of users in the tomcat-users.xml that is embedded in eclipse you must restart eclipse not just the server for the new users to be recognised. I guess that eclipse caches the tomact-user.xml file.

Tomcat 7 - Multiple security-constraints not working

Running Tomcat 7, I am trying to configure the /conf/web.xml on the Tomcat server to secure some URLs with basic authentication and to provide some other URLs for public access.
The tomcat-users.xml contains following role and user:
<role rolename="test-ui"/>
<user username="paul" password="password" roles="test-ui"/>
I have added the following section to Tomcats /conf/web.xml
<security-constraint>
<web-resource-collection>
<web-resource-name>Public access</web-resource-name>
<url-pattern>/docs/*</url-pattern>
</web-resource-collection>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Protected access</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>test-ui</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<description>Protected access</description>
<role-name>test-ui</role-name>
</security-role>
<login-config>
<auth-method>BASIC</auth-method>
</login-config>
So there are two 'security-constraint' elements, the public one does not contain the 'auth-constraint', which actually should mean, there is no authentication necessary.
When I open the URL
http://localhost:8080
Tomcat asks for authentication.
This is fine, however when I open the URL
http://localhost:8080/docs/
Tomcat also asks for authentication and for my understanding this is configured as a "non secure" URL - so public acccess, but it does not behave like this.
What did I wrong in the configuration or is this scenario not supposed to work like this?
Thanks.
Paul
You need the <auth-constraint> node in the <security-constraint>, even it is empty e.g. <auth-constraint/>
If an security-constraint does not exists, the Container MUST allow unauthenticated access for these URL. security-constraint is optional.

Welcome page is displayed without being redirected to login page

I have following web.xml file I kept welcome page into security check so that it would redirect to login page but the welcome page is displayed without user loggin in. Is this the correct way?
<welcome-file-list>
<welcome-file>/GISPages/welcome.xhtml</welcome-file>
</welcome-file-list>
<resource-ref>
<res-ref-name>jdbc/Gis_WebApp</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<security-constraint>
<web-resource-collection>
<web-resource-name>Protected Pages</web-resource-name>
<url-pattern>/GISPages/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>registereduser</role-name>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>Live</realm-name>
<form-login-config>
<form-login-page>/login.xhtml</form-login-page>
<form-error-page>/noauth.xhtml</form-error-page>
</form-login-config>
</login-config>
<security-role>
<role-name>registereduser</role-name>
</security-role>
<security-role>
<role-name>admin</role-name>
</security-role>
Security constraints protects a URL pattern, but in this case due to welcome-file setting your default URL will change to something like http://:port/webcontext/ and welcome.xhtml will be displayed. Whereas as per the URL pattern defined a protected URL should have URL like http://:port/webcontext/GISPages/welcome.xhtml
Since the URL pattern did not match the application server render the page content.
Only solution which worked for me is to check UserPrincipal in prerender event
<f:event type="preRenderComponent"
listener="#{bean.forwardToLoginIfNotLoggedIn}" />
and redirect to login.xhtml if UserPrincipal returns null.
Apologies for opening an old thread. I recently faced similar issue hence thought that this might be useful to some.

WebLogic simple realm (like tomcat-users.xml)

Like this fellow here, I'm trying to port a Tomcat application to WebLogic.
I have a few resources protected by security rules in web.xml. Instead of BASIC, I'm using FORM authentication, but that should be irrelevant.
In Tomcat, it's very easy to set up a simple security realm, by editing conf/tomcat-users.xml.
How do I set up a simple security realm in Weblogic ? All I want is to have the user to input his username and password and have it authenticated by the container.
<security-constraint>
<web-resource-collection>
<web-resource-name>basic-auth security</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>HELLO_USER</role-name>
</auth-constraint>
<user-data-constraint>NONE</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>somerealm</realm-name>
<form-login-config>
<form-login-page>login.jsp</form-login-page>
<form-error-page>error.jsp</form-error-page>
</form-login-config>
</login-config>
<security-role>
<role-name>HELLO_USER</role-name>
</security-role>
there is a default weblogic realm called "myrealm". Create the user(s) there using the weblogic web console. Also create a group (i.e. HELLO_GROUP) and assign your user(s) to that group.
Create a weblogic.xml file and map the HELLO_USER role onto the HELLO_GROUP with a structure like:
<weblogic-web-app>
...
<security-role-assignment>
<role-name>HELLO_USER</role-name>
<principal-name>HELLO_GROUP</principal-name>
</security-role-assignment>
...
</weblogic-web-app>

How to use htpasswd protection in Tomcat?

I have already created a user database file using Apache's htpasswd command. This file is now used by several other application like apache and subversion.
Users in are created like this:
htpasswd /path/to/users.htpasswd peter
This user file is global, not per directory.
How I can make Tomcat 6 use this same file as a security realm?
Most similar to the htpasswd may be the MemoryRealm.
I had problems myself to find a simple example how to use it, so I'll post an easy example code here:
Set up a role, username and password in tomcat-users.xml
Your web.xml should contain something like:
<security-constraint>
<web-resource-collection>
<web-resource-name>
My Protected WebSite
</web-resource-name>
<url-pattern> /* </url-pattern>
<http-method> GET </http-method>
<http-method> POST </http-method>
</web-resource-collection>
<auth-constraint>
<!-- the same like in your tomcat-users.conf file -->
<role-name> test </role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method> BASIC </auth-method>
<realm-name> Basic Authentication </realm-name>
</login-config>
<security-role>
<description> Test role </description>
<role-name> test </role-name>
</security-role>
Add this to your server.xml file:
<Realm className="org.apache.catalina.realm.MemoryRealm"></Realm>
To secure access to your Tomcat webapp, you can implement your simple security constraint (e.g. in /var/lib/tomcat7/webapps/*/WEB-INF/web.xml) as below (just add it before </web-app> ending):
<!-- This security constraint protects your webapp interface. -->
<login-config>
<!-- Define the Login Configuration -->
<auth-method>BASIC</auth-method>
<realm-name>Webapp</realm-name>
</login-config>
<security-constraint>
<web-resource-collection>
<web-resource-name>Admin</web-resource-name>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
<!-- Specifying a Secure Connection -->
<user-data-constraint>
<!-- transport-guarantee can be CONFIDENTIAL (forced SSL), INTEGRAL, or NONE -->
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<!-- Authorization, see: tomcat-users.xml -->
<security-role>
<role-name>*</role-name>
</security-role>
The login-config element contains the auth-method element, which specifies the authentication method that we use, which is BASIC. The security-constraint element contains 3 elements: web-resource-collection, auth-constraint, and user-data-constraint. The web-resource-collection specifies the parts of our application that require authentication. The /* indicates that the whole application requires authentication. The auth-constraint specifies the role that a user needs to have in order to access the protected resources. The user-data-constraint's transport-guarantee can be NONE, CONFIDENTIAL or INTEGRAL. We set it to NONE, which means that redirecting to SSL is not required when you try to hit the protected resource.
Also make sure that you've line:
<Realm className="org.apache.catalina.realm.MemoryRealm" />
inside your conf/server.xml (Engine section).
If you have not changed any configuration files, please examine the file conf/tomcat-users.xml in your installation (locate tomcat-users.xml). That file must contain the credentials to let you use Tomcat webapp.
For example, to add the manager-gui role to a user named tomcat with a password of s3cret, add the following to the config file listed above:
<role rolename="manager-gui"/>
<user username="tomcat" password="s3cret" roles="manager-gui"/>
Then you can access your webapps manager from /manager/html (e.g. reloading after config changes).
Read more: Manager App HOW-TO.
Then restart your Tomcat and when accessing your webapp, it should ask you for the right credentials.
See also:
HTTP Basic Authentication in Java at Oracle site
Specifying an Authentication Mechanism in Java at Oracle site
Realm Configuration HOW-TO at Apache Tomcat site
Setting up role based security in tomcat
How do I use Basic authentication with Tomcat?
There are two options:
Use Apache as a front end to the tomcat (using either mod_jk or mod_proxy_ajp) and the Apache do the authentication. You can find details on how to do so here
If you want the tomcat to do the authentication, then you need ot use something else than the htpasswd file. There are 4 ways to save the users' credentials - using database, JNDI/LDAP, an XML file or a JAAS provider. You can read about all the options in the Realm Configuration HOW-TO.

Resources