I am not sure what I am doing wrong here but when I put the faces context twice in the URL it bypasses all of my Realm Securities.
My URL Pattern:
<servlet-mapping>
<servlet-name>Faces</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
Security Constraint
<security-constraint>
<display-name>ADMIN</display-name>
<web-resource-collection>
<web-resource-name>Protected Admin Area</web-resource-name>
<description/>
<url-pattern>/faces/admin/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<description/>
<role-name>ADMIN</role-name>
</auth-constraint>
<user-data-constraint>
<description/>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
So when i goto: http://domain.com/faces/admin/index.xthml i do get the proper response i am looking for.
But if i goto: http://domain.com/faces/faces/admin/index.xhtml it completely lets me in regardless of the fact that the servlet is slated to be at /admin* I am assuming the * at the end of admin is what is causing it. But how can I solve this to where domain.com/faces/faces is invalid, and only domain.com/faces is valid?
I cannot seem to find anyone else facing this issue. So i must be doing something wrong.
Thank you
First, the good news: You're not doing anything wrong.
To solve: Use the extension mapping variant on the FacesServlet
<servlet-mapping>
<servlet-name>Faces</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
The bad news: This might be a bit of an oversight (read:flaw) in the request matching model.
My hypothesis is that the URL matching model of the FacesServlet doesn't work well with the standard servlet container request matching model.
In an ideal situation (without JSF), /faces/faces/admin/index.xhtml must correspond either a servlet or a specific resource. The container will attempt to verify if it's a valid resource and then whether the resource is a constrained resource.
The problem here is that the container takes the resource constraints very literally, meaning that it looks for the closest literal match to that URL in the security table. If it doesn't resolve the resource as being restricted, it serves the resource without interfering.
When you define /faces/admin/* as a protected resource, request a /faces/faces/admin/admin.xhtml and then also have a /faces/* servlet mapping, the container attempts to verify that /faces/faces/admin/index.xhtml is a constrained resource (and it's not). Since the container has no reason to hold up the request any further, it hands the request over to FacesServlet and then FacesServlet appears to just blindly strip all references to faces in the requestURL (because you've said OK to /faces/*) and serve anything that's left.
This is the reason why the file-extension servlet definition appears to be immune to it; in the case of the file extension mapping, the FacesServlet must find a literal resource in your folder structure that corresponds to that URL even before the container gets to determine that the resource is constrained or not
Verify this theory and there might be a need to file a critical JIRA with the mojarra team.
Related
I'm implementing role-based authorization in my application following the structure of the java ee 8 jwt security sample: https://github.com/javaee-samples/javaee8-samples/tree/master/security/jwt.
I have a back-end application with session-based security and JSF. Authentication and Authorization is managed by a WebFilter:
#WebFilter(urlPatterns = "/faces/*")
public class AuthorizationFilter implements Filter {
}
I have a REST api with JWT token-based security where I want to implement HttpAuthenticationMechanism for managing authentication and authorization.
I want these two different security mechanisms to live next to each other for personal interest and to prove that I can implement both ways. However, the HttpAuthenticationMechanism gets called everytime, also when browsing my JSF application. This leads to triggering of both mechanisms that are conflicting.
Is it possible to apply the HttpAuthenticationMechanism to only a certain url path? Like the urlPattern that's used in WebFilter? If so, how does one?
I want to use the HttpAuthenticationMechanism only to be triggered in my rest application:
#ApplicationPath("rest")
public class RestApplication extends Application {
public RestApplication() {
}
}
There is a method "isProtected" in HttpMessageContext which will set to true/false depending on the security-constraints in web.xml
public AuthenticationStatus validateRequest(HttpServletRequest request,
HttpServletResponse response, HttpMessageContext httpMessageContext) throws AuthenticationException {
if (!httpMessageContext.isProtected()) {
return httpMessageContext.doNothing();
}
...
So the first thing to do is check isProtected and only continue if the resource is supposed to be protected.
Now you can use security-constraint in web.xml as usual:
...
<security-constraint>
<web-resource-collection>
<web-resource-name>Restricted</web-resource-name>
<description>Declarative security tests</description>
<url-pattern>/protected/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>somegroup</role-name>
</auth-constraint>
<user-data-constraint>
<description>no description</description>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<security-role>
<description>Somegroup</description>
<role-name>somegroup</role-name>
</security-role>
...
Now authentication will only be done for URLs below the /protected/* pattern, anything else will be available unprotected
Wondering why this is not addressed in most of the tutorials/examples out there...
Credits goes to this link which seems to be the only one describing this (althoug there is a a missing "NOT" in the Listing No 16)
https://www.informatik-aktuell.de/entwicklung/programmiersprachen/authentication-mit-java-ee-8.html
I have a problem with configuration ( or basic understanding how things work at background). I create a JAVAEE project by checking Web application and ReSt api checkbox ( in intellij with glassfish 5.0). I have sample code below which web methods work but welcome page does not work. My web.xml and sample web service methods are below.
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>test</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
**<url-pattern>/ *</url-pattern>**
</servlet-mapping>
#Path("/RestTest")
public class TestString {
#Context
ServletContext context;
#GET
#Path("insertdb/{param1}/{param2}")
#Produces(MediaType.APPLICATION_JSON)
public Object writeToDb( #PathParam("param1") String param1
,#PathParam("param2") String param2){
try{
String password= context.getInitParameter("DbPassword");
Class.forName("org.mariadb.jdbc.Driver");
Connection dbCon = DriverManager.getConnection(
"jdbc:mariadb://xxx/testdb", "root", password);
PreparedStatement stmt=dbCon.prepareStatement(
"INSERT INTO TestTable VALUES(?,?)");
stmt.setString(1,param1);
stmt.setString(2,param2);
stmt.executeUpdate();
dbCon.close();
return "Success";
}catch(SQLException | ClassNotFoundException ex){
return ex.toString();
}
}
#GET
#Path("sum/{sum1}/{sum2}")
#Produces(MediaType.TEXT_HTML)
public String calculateSum(#PathParam("sum1") int param1
,#PathParam("sum2") int param2){
return ""+(param1 + param2);
}
If i change this line url-pattern "/*" to "/"
then welcome page is accessible but not methods.
Thus what i want is, having a welcome page which i will use for documentation for my web services(i dont want SOAP) and web methods must work by adding / to base url. How can i achieve that and what is difference between /* and /
See here for explanation of differences:
What is url-pattern in web.xml and how to configure servlet
Generally for a rest api it is best to use a path specific to all rest calls, for instance http://localhost/mywebapp/rest/...
Something like:
<servlet-mapping>
<servlet-name>jersey-servlet/servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
You only want jersey serving particular URLs when it is bundled in a WAR that also includes html pages.
To answer your question, difference between "/" and "/*"
A mapping that contains the pattern "/" matches a request if no other pattern matches. This is the default mapping. The servlet mapped to this pattern is called the default servlet. The default mapping is often directed to the first page of an application. Example :
Both requests will display same contents from index.jsp
http://myhost.com/index.jsp
and
http://myhost.com/
Now, a mapping that contains "/*" overrides all other servlets, including all servlets provided by the servlet container such as the default servlet and the JSP servlet. Whatever request you fire, it will end up in that servlet. This is thus a bad URL pattern for servlets.
Possible solution for your issue
Change the URL pattern to specific instead of default pattern.
<servlet>
<servlet-name>webservice</servlet-name> //servlet name
<servlet-class>com.rest.MyRestServlet</servlet-class> //servlet class
</servlet>
<servlet-mapping>
<servlet-name>webservice</servlet-name> //servlet name
<url-pattern>/RestTest/*</url-pattern> //all webservice request
</servlet-mapping>
All the web service request are accessible through
http://myhost.com/RestTest/
You may also be interested to look
What is URL-pattern in web.xml and how to configure servlet
Basics of Java Servlet
Servlet configuration and url-pattern
As you highlighted, your problem revolves around those four lines:
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
As Jim Weaver mentioned, it's a matter of url-pattern.
Solution(s)
You may consider three solutions (from the most-preferred to least-preferred):
dedicated REST URL: the easiest way is to have a dedicated url-pattern such as /rest/* for your web services. You can benefit some assets such as url hierarchy or you can easily implement a security framework over it.
URL rewriting may be an option and this answer suggests some library. I haven't tested those libraries myself
Page redirection can be an option to go around REST filtering but in the specific case of having the url-pattern at /*, I have to say I'm not sure if it's working for the reason I'll explain in next section
now a bit of explanation of what happened
Why setting the url-pattern at /* prevent from accessing the welcome page?
Actually, it's not only the welcome page that is not accessible: it's all the resources under the defined url-pattern. Whatever get in touch with REST stays with REST... Here is the schema taken from JSR 339 Appendix C:
With a GlassFish 5.0, I guess you're using JAX-RS 2.1 (JSR 370) but the sections I'm quoting have the same content
Without entering into detail, it is visible that only ContainerRequest Filters are executed in the process. Especially, it's worthy to notice that after Request Matching, requests are not forwarded to any servlet in a sense that standard resources are not reachable, unless specified by the REST method.
It's also worthy to highlight the fact the servlet filters are executed beforehand (leveraging this point is absolutely vital for managing security for example). I did not find back the source proving this point but I know it's somewhere on the web ^^.
Request matching is defined at section 3.7.2. In a nutshell, it is in three steps where the first one is the most important for your question, especially at step D:
Identify a set of candidate root resource classes matching the request
c. ...
d. If [the set of classes whose path matches the request URL] is empty then no matching resource can be found, the algorithm terminates and an implementation MUST generate a NotFoundException (404 status) and no entity
e. ...
highlights are mine.
The two last steps are
Obtain a set of candidate resource methods for the request
Identify the method that will handle the request
TL;DR
What happened when you set <url-pattern>/*<url-pattern> and tries to access to your welcome page (or any page actually):
Your server receives the GET request
If there are filters (such those from a security framework), there are executed
REST enters the scene
Pre Match filters are executed (none if your case)
Fetch your root resources classes (in your example, all classes in the test package)
Find if one of those class match the request URL
None are found, a 404 status is returned
To avoid unnecessary URL conflicts, the best options would be having a dedicated URL for your REST methods
If you mention in web xml like following all the request receive by 'Jersey Web Application' servlet. so request to index.jsp also redirect to 'Jersey Web Application' servlet
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
To avoid this add some prefix to the url to separate rest request like following
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>rs/*</url-pattern>
</servlet-mapping>
The servlet config looks like this -
<servlet>
<servlet-name>smart</servlet-name>
<servlet-class>SuperSmart</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>smart</servlet-name>
<url-pattern>/dumb</url-pattern>
</servlet-mapping>
Its said that all these aliases are for security. I get that. But why do we have to map it to a servlet-name first and then to the servlet-class ? Why can't the server find the url pattern and directly map it to the servlet-class ?
The aim of this is that the servlet could be referenced by more than one mapping, so you can map one servlet to more than one url (or pattern) and not just one.
The name is sort of like and "ID" that tells the container which <servlet> part goes with which <servlet-mapping> part (as well as ties it to other parts of the XML config in container specific XML files)
You can have multiple url patterns tied to the same servlet name.
I agree it seems ugly, but it's an attempt to keep the servlet config DRY, as servlet-name can be used in filter-mappings as well as servlet-mappings.
In servlet spec 3.0 you can annotate the servlets themselves which is neater.
It was designed that way to allow other components, such as filters, can access it. Filters can either be associated with a Servlet by using the <servlet-name> style:
<filter-mapping>
<filter-name>Image Filter</filter-name>
<servlet-name>ImageServlet</servlet-name>
</filter-mapping>
In my web.xml I have URL pattern for servlet like this:
<url-pattern>/*/myservice</url-pattern>
So I want to call it using blablabla/myservice also as anyWord/myservice.
But it doesn't work. It work only if I call it using this URL: /*/myservice (with asterisk in URL).
You can't do that.
According to the Servlet 2.5 Specification (and things aren't that different in other levels of the specification), chapter SRV.11.2:
A string beginning with a / character and ending with a /* suffix
is used for path mapping.
A string beginning with a *. prefix is used as an extension mapping.
A string containing only the / character indicates the "default" servlet of the application. In this case the servlet path is the request URI minus the context path and
the path info is null.
All other strings are used for exact matches only.
Your case falls under the 4th bullet, so exact mapping is used.
To circumvent that, use a mapping of / (third case). Map all requests to go to a particular servlet, and have that servlet re-route requests to handlers of some sort (either other servlets, or some custom classes).
For example:
<url-pattern>/</url-pattern>
<servlet-name>MyServlet</servlet-name>
And then, within MyServlet's code, inspect the URL that you received in the request (using request.getPathInfo()) and use the value to forward the request to other handlers.
You could use a filter while your url pattern is /* and inside the filter decide which redirection you required.
<filter>
<display-name>MyFilter</display-name>
<filter-name>MyFilter</filter-name>
<filter-class>com.MyfilterClass</filter-class>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</filter>
What about two ULR-mapping sections?
<servlet-mapping>
<servlet-name>ModifyMemberSVL</servlet-name>
<url-pattern>/ModifyMember</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ModifyMemberSVL</servlet-name>
<url-pattern>/Administration/Add_Member/ModifyMember</url-pattern>
</servlet-mapping>
I've a Java GAE app that should clear the memcache whenever I deploy a new version of the app. I'm using static initializer, i.e.
static {
MemcacheServiceFactory.getMemcacheService().clearAll();
}
However, that would clear the memcache as well whenever a new instance is started, which is not desired behavior.
What is the proper way to execute initialization code?
TIA
I create my memcache keys using a factory and they always get appended with the version number of my app so when i upload a new version, the keys are new I forget about the old cached values, which will go away on their own.
I also have a servlet defined in web.xml with a security constraint for admin only, then I browse to it's URL (/admin/example) manually after an upgrade - logging in as as admin. The servlet has my run once code in it to kick off any tasks for upgrading store data and purging the cache.
<security-constraint>
<web-resource-collection>
<url-pattern>/admin/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
One time initializations of applications can be done in the init() method of the Servlet. Here is an example
public class CatalogServlet extends HttpServlet {
private BookDB bookDB;
public void init() throws ServletException {
bookDB = (BookDB)getServletContext().
getAttribute("bookDB");
}
In the above example, the ServletContext attribute is, of course, just a variable that exists between servlet calls (the normal way to maintain state). This, of course, assumes that you somewhere else stored this variable in the ServletContext. The other way is to create the variable in the deployment descriptor.
To set initialization parameters within your deployment descriptor (web.xml), here is an example:
<servlet
<servlet-name...
<servlet-class ...
<init-param>
<param-name>param1</param-name>
<param-value>value1</param-value>
</init-param>
</servlet>
If this doesn't answer it, please clarify "whenever a new instance is started".