Thursday Oct 29, 2009
In May 2009, I discussed the Servlet 3.0 security annotations in one of my blogs,
Servlet 3.0 Security Annotations.
At that time, the annotations were defined similar to those in EJB.
During the discussion in JSR 315 expert group, two issues were identified as follows:
- In JSR 250, type level annotations only apply to methods declared in that class, not those inherited. This is an issue for servlets as they extend
javax.servlet.http.HttpServlet.
- The
doGet method et al may not correspond to http method GET et al as the logic can be overrided in service method of the servlet.
Thanks to Ronald Monzilo for discussions in Servlet 3.0 security.
The following is the update on Servlet 3.0 security annotations:
- As in servlet 2.5, @DenyAll, @PermitAll, @RolesAllowed will not apply to servlets.
@TransportProtected will not be added to JSR 250.
- The following new annotations will be added to javax.servlet.annotation:
- ServletSecurity
- HttpConstraint
- HttpMethodConstraint
Note that @ServletSecurity is a type level annotation and the rests are used as parameters in @ServletSecurity.
- With the above new annotations, one can resolve the issue mentioned above. In addition, it covers the new use case where one want to have security constraint for extended http methods only, for instance FOO.
In this blog, I will illustrate how those annotation work. For convenient of readers of my previous blogs, I will first illustrate the four scenarios mentioned in my previous blog, Servlet 3.0 Security Annotations with the new annotations. Then I have an additional example.
Example 1: For all Http Methods
@WebServlet("/myurl")
@ServletSecurity(@HttpConstraint(rolesAllowed={"javaee"}))
public class TestServlet extends HttpServlet {
...
}
In this case, all http methods are protected and accessible only by users with role javaee.
Example 2: Http Method Level
@WebServlet("/myurl")
@ServletSecurity(httpMethodConstraints={ @HttpMethodConstraint("GET"),
@HttpMethodConstraint(value="POST", rolesAllowed={"javaee"}),
@HttpMethodConstraint(value="TRACE", emptyRoleSemantic=ServletSecurity.EmptyRoleSemantic.DENY) })
public class TestServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
...
}
protected void doPost(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
...
}
protected void doTrace(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
...
}
}
The behaviors of the above servlet can be summarized as follows:
| Http method | Behavior
|
|---|
| GET | all can access GET method
|
| POST | only authenticated users with role javaee can access POST method
|
| TRACE | no one can access TRACE method
|
Example 3: A General Constraint for all Http methods with some Exceptional Cases
@WebServlet("/myurl")
@ServletSecurity(value=@HttpConstraint(rolesAllowed={"javaee"}),
httpMethodConstraints={ @HttpMethodConstraint(value="POST", rolesAllowed={"staff"}),
@HttpMethodConstraint("TRACE") })
public class TestServlet extends HttpServlet {
...
protected void doPost(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
...
}
protected void doTrace(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
...
}
}
The behaviors of the above servlet can be summarized as follows:
| Http method | Behavior
|
|---|
| POST | only authenticated users with role staff can access POST method
|
| TRACE | all can access TRACE method
|
| methods other than POST and TRACE | only authenticated users with role javaee can access
|
Note that in the previous definitions, the exceptional cases must be the standard http methods. There is no such restriction for the new annotations as illustrated by the Example 5 below.
Example 4: Https and protected for a given role
@WebServlet("/myurl")
@ServletSecurity(value=HttpConstraint(
transportGuarantee=ServletSecurity.TransportGuarantee.CONFIDENTIAL),
httpMethodConstraints={ @HttpMethodConstraint(value="TRACE", transportGuarantee=ServletSecurity.TransportGuarantee.NONE, rolesAllowed={"javaee"}) })
public class TestServlet extends HttpServlet {
...
protected void doTrace(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
...
}
}
The behaviors of the above servlet can be summarized as follows:
| Http method | Behavior
|
|---|
| TRACE | Https is supported. It just is not required. Only authenticated users with role javaee can access TRACE method
|
| methods other than TRACE | require https
|
Example 5: Protect FOO only
@WebServlet("/myurl")
@ServletSecurity(value=@HttpConstraint,
httpMethodConstraints={ @HttpMethodConstraint(value="FOO", rolesAllowed={"javaee"}) })
public class TestServlet extends HttpServlet {
...
}
The behaviors of the above servlet can be summarized as follows:
| Http method | Behavior
|
|---|
| FOO | only authenticated users with role staff can access POST method
|
| methods other than FOO | all can access
|
Thursday May 07, 2009
In JSR 315: Java Servlet 3.0 Specification,
web-fragment.xml is introduced for pluggability of library jars which are
packaged under WEB-INF/lib.
The content of web.xml and web-fragment.xml are almost the same.
One can define servlets, filters and listeners there. One can also specify
metadata-complete=true in a given web-fragment.xml.
In the latter case, the annotation processing of classes in that jar would be skipped.
With web-fragment.xml, library jars can be self-contained and provide web
related metadata information.
The basic differences of web.xml and
web-fragment.xml are summarized in the following table:
| | web.xml | web-fragment.xml
|
|---|
| Location | WEB-INF of the war file | META-INF directory of JAR file inside WAR file's WEB-INF/lib
|
| Ordering related element | <absolute-ordering> | <ordering>
|
Ordering of web fragments
If there are more than one web-fragment jars, then one may like to specify the
order of processing web-fragment.xml and annotations.
This is important. For instance, filters will be executed in the order specified in
web.xml.
Similary for listeners. In Servlet 3.0,
<absolute-ordering> is introduced in
web.xml and
<ordering> is introduced in
web-fragment.xml.
The ordering of web-fragments is specified in the following priority:
- from
<absolute-ordering> in web.xml if it exists
- from
<ordering> for each web-fragment.xml if it exists
- otherwise unspecified
absolute-ordering in web.xml
The
<absolute-ordering> in
web.xml provides a way to specify
the ordering of loading
web-fragment.xml and annotation processing
of web fragment.
For instance,
<web-app>
...
<absolute-ordering>
<name>A</name>
<others/>
<name>B</name>
<absolute-ordering>
</web-app>
In the above example, the web fragment A would be processed first
and web fragment B would be processed last.
Note the name A and B are specified in
name element of
web-fragment.xml (see examples below).
ordering in web-fragment.xml
If there is no
<absolute-ordering> in
web.xml, then one would look at
<ordering> in
web-fragment.xml. The details are described in
section 8.2.3 of Servlet 3.0 spec.
Let us look at some examples.
- There is only one jar having
<ordering> in web-fragment.xml.
<web-fragment>
<name>A</name>
...
<ordering>
<before>
<others/>
</before>
</ordering>
</web-fragment>
In this case, web-fragment A would be processed first.
- There are two jars having
<ordering> in web-fragment.xml, namely
web-fragment A:
<web-fragment>
<name>A</name>
...
<ordering>
<before>
<others/>
</before>
</ordering>
</web-fragment>
web-fragment B:
<web-fragment>
<name>B</name>
...
<ordering>
<before>
<others/>
</before>
</ordering>
</web-fragment>
Both web-fragment A and B would like to be processed first. In this case, one only
guarantee that both A and B are processed before other web-fragments.
But the ordering of A and B are not determined, that is arbitrary in this case.
- There are two jars having
<ordering> in web-fragment.xml, namely
web-fragment A:
<web-fragment>
<name>A</name>
...
<ordering>
<before>
<others/>
</before>
</ordering>
</web-fragment>
web-fragment B:
<web-fragment>
<name>B</name>
...
<ordering>
<after>
<name>A</name>
</after>
<before>
<others/>
</before>
</ordering>
</web-fragment>
In this case, A would be processed first, then followed by B, and then other web-fragments.
If one would like to have a deterministic ordering, then I would recommend to use
absolute-ordering in
web.xml.
Monday May 04, 2009
In Servlet 2.5, only @DeclareRoles and @RunAs are supported in servlets.
And @DenyAll, @PermitAll, @RolesAllowed are only supported for EJBs.
In JSR 315: Java Servlet 3.0 Specification,
@DenyAll, @PermitAll, @RolesAllowed will be supported in servlets.
Furthermore, it supports
JSR 250: Common Annotations for the Java Platform MR1:
- @TransportProtected, a new annotation indicates whether the transport is confidential or none.
- @DenyAll will also be available at the TYPE level.
The mapping of the @DenyAll, @PermitAll, @RolesAllowed and @TransportProtected to
security constraint are described in Chapter 13.4.1 of
Servlet 3.0 specification.
These annotations can be applied to:
- the servlet class
- one of the following methods in HttpServlet:
- doDelete
- doGet
- doHead
- doOptions
- doPost
- doPut
- doTrace
Note that method level authorization annotations (@DenyAll, @PermitAll, @RolesAllowed)
override those in class level for the associated http method.
Similarly, method level @TransportProtected overrides the one in class level.
In this blog, we illustrate the usages of these annotations by examples.
Example 1: Type Level
@WebServlet("/myurl")
@RolesAllowed("javaee")
public class TestServlet extends HttpServlet {
...
}
In this case, all http methods are protected and accessible only by users with role javaee.
Example 2: Method Level
@WebServlet("/myurl")
public class TestServlet extends HttpServlet {
@PermitAll
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
...
}
@RolesAllowed("javaee")
protected void doPost(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
...
}
@DenyAll
protected void doTrace(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
...
}
}
The behaviors of the above servlet can be summarized as follows:
| Http method | Behavior
|
|---|
| GET | all can access GET method
|
| POST | only authenticated users with role javaee can access POST method
|
| TRACE | no one can access TRACE method
|
Example 3: Type and Method Level
@WebServlet("/myurl")
@RolesAllowed("javaee")
public class TestServlet extends HttpServlet {
...
@RolesAllowed("staff")
protected void doPost(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
...
}
@PermitAll
protected void doTrace(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
...
}
}
The behaviors of the above servlet can be summarized as follows:
| Http method | Behavior
|
|---|
| POST | only authenticated users with role staff can access POST method
|
| TRACE | all can access TRACE method
|
| methods other than POST and TRACE | only authenticated users with role javaee can access
|
Example 4: @TransportProtected and @RolesAllowed
@WebServlet("/myurl")
@TransportProtected
public class TestServlet extends HttpServlet {
...
@TransportProtected(false)
@RolesAllowed("javaee")
protected void doTrace(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
...
}
}
The behaviors of the above servlet can be summarized as follows:
| Http method | Behavior
|
|---|
| TRACE | no https, only authenticated users with role javaee can access TRACE method
|
| methods other than TRACE | require https
|
Tuesday Dec 02, 2008
The JSR 315: Java Servlet 3.0 Specification
expert group is in the process of making
Public Review available. You can look at Rajiv's blog for more details.
The reference implementation is available
in GlassFish v3 nightly build.
In Servlet 3.0, for ease of development, several new annotations are defined.
These annotations are resided in the package javax.servlet.annotation.
They are intended to provide meta data only. In other words, one still need
to extend the corresponding class or implement the corresponding interface.
Now, one can have Servlet, Filter
and ServletContextListener in a war file without web.xml.
In this blog, I will discuss the following annotations:
- @WebServlet
- @ServletFilter
- @WebServletContextListener
Servlet Annotation ( @WebServlet )
In JSR 315, one can specify the servlet meta data by using
@WebServlet.
For instance,
@WebServlet(name="mytest",
urlPatterns={"/myurl"},
initParams={ @InitParam(name="n1", value="v1"), @InitParam(name="n2", value="v2") })
public class TestServlet extends javax.servlet.http.HttpServlet {
....
}
In this example, the class TestServlet is a servlet as it
extends HttpServlet.
The @WebServlet provides the following meta data:
- the name of the servlet,
mytest, corresponds to <servlet-name> under <servlet> in web.xml
- the url pattern of the servlet,
/myurl, corresponds to <url-pattern> under <servlet-mapping> in web.xml
- initialization parameters of the servlet,
n1=v1, n2=v2, corresponds to <init-param> under <servlet> in web.xml
<init-param>
<param-name>n1</param-name>
<param-value>v1</param-value>
</init-param>
<init-param>
<param-name>n2</param-name>
<param-value>v2</param-value>
</init-param>
Note that in this case, @InitParam is used to specify the name/value pairs.
Servlet Filter Annotation ( @ServletFilter )
One can specify the servlet filter meta data by using
@ServletFilter.
For instance,
@ServletFilter(urlPatterns={"/myurl"}.
initParams={ @InitParam(name="mesg", value="my filter") })
public class TestFilter implements javax.servlet.Filter {
....
public void init(FilterConfig filterConfig) throws ServletException {
....
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
....
}
public void destroy() {
....
}
}
In this example, the class TestFilter is a servlet filter as it
implements Filter.
The @ServletFilter provides the following meta data:
- the url pattern of the filter applied,
/myurl
- initialization parameter of the filter,
mesg=my filter, corresponds to <init-param> under <filter> in web.xml
Note that in this case, @InitParam is used to specify the name/value pairs.
Servlet Context Listener Annotation ( @WebServletContextListener )
One can specify the servlet content listener met data by using
@WebServletContextListener/code>. For instance,
@WebServletContextListener
public class TestServletContextListener implements javax.servlet.ServletContextListener {
....
public void contextInitialized(ServletContextEvent sce) {
....
}
public void contextDestroyed(ServletContextEvent sce) {
....
}
}
In this example, the class TestServletContextListener is a servlet
context listener as it implements ServletContextListener.
The @WebServletContextListener provides the meta data that this is a servlet context listener in a given war file.