I want to make my webapp license protected. When any page/resource of webapp is requested, I want to first check for the license. If license is not found then I want to redirect to license upload page.
I have created a filter which maps to all the requests where I can check for license and redirect if necessary. The problem is that my webapp has security constraint of login authentication. see web.xml at the end for more information.
Because of the security constraint, all the requests are first intercepted by login authentication and then forwarded to my filter. However, I want to check for license before the login can happen.
Here is a related question I asked.
Java : Intercept all requests before they go to login authentication
Prioritizing filter over the security constraint seems to be impossible. So, I want to ask is there any other way I can approach this use case?
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>Tango</display-name>
<filter>
<filter-name>SalsaValidationFilter</filter-name>
<filter-class>net.semandex.salsa.validationFilters.SalsaValidationFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SalsaValidationFilter</filter-name>
<url-pattern>/*</url-pattern>
<!-- <servlet-name>SalsaValidationServlet</servlet-name> -->
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<session-config>
<session-timeout>20</session-timeout>
</session-config>
<security-constraint>
<web-resource-collection>
<web-resource-name>Login page images</web-resource-name>
<url-pattern>/images/salsadb-logo2.png</url-pattern>
<url-pattern>/images/salsa-icon.png</url-pattern>
<url-pattern>/images/shadow_box.png</url-pattern>
<url-pattern>/images/header.png</url-pattern>
<url-pattern>/images/bg.png</url-pattern>
<url-pattern>/css/splash.css</url-pattern>
<url-pattern>/WEB-INF/licenseValidation.html</url-pattern>
<url-pattern>/auth/licenseValidation.html</url-pattern>
</web-resource-collection>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>The entire webapp</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>SalsaUser</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>SalsaUser</role-name>
</security-role>
<login-config>
<auth-method>FORM</auth-method>
<form-login-config>
<form-login-page>/auth/login.jsp</form-login-page>
<form-error-page>/auth/loginError.jsp</form-error-page>
</form-login-config>
<realm-name>mongo_login</realm-name>
</login-config>
</web-app>
If you must verify the license before authentication, the only way would be using programmatic security and including the license verification as part of the process.
Programmatic security is useful when declarative security alone is not sufficient to express the security model of an application. The API for programmatic security consists of methods of the EJBContext interface and the HttpServletRequest interface. These methods allow components to make business-logic decisions based on the security role of the caller or remote user.
https://docs.oracle.com/javaee/7/tutorial/security-intro003.htm#BNBXH
Here are a few short examples: https://docs.oracle.com/javaee/7/tutorial/security-webtier003.htm#GJIIE
I haven't done programmatic security myself but from the looks of it you could do something like this:
Make sure you redirect to a different path, so those pages don't call the filters again and loop. (Filters can be configured to be skipped when forwarding/redirecting and I think that's the default, but if you had to drop the security constraint then you want to be sure they are called no matter what.)
You might do all this in a single filter and/or instead of redirecting when failing write out the appropiate response (kinda simulating a servlet POSTing to himself several times). A filter is better for this than a servlet because you can be sure it was called for any access attempt.
Another way would be to write everything in 2) and 3) as a single servlet aside from the "real" app and have a filter redirecting to it if the session isn't authenticated and doesn't have the proper "valid-license" attribute set (you set it in the servlet). This might be faster and perhaps simpler to maintain but not so tightly coupled.