users@jersey.java.net

Re: [Jersey] authorization and uri templates

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Fri, 20 Nov 2009 12:12:19 +0100

Hi Robert,

You can use a Resource filter and your own security-based annotation
that obtains the path parameter and utilizes the SecurityContext.

I have included a ResourceFilterFactory implementation to support the
@RolesAllowed annotation. This supports the processing of
@RolesAllowed annotations on resource methods and sub-resource
locators. So you should be able to copy this code and adapt it to your
needs.

You can inject the UriInfo to obtain the "username" path parameter.
Your annotation could declare the path parameter name that needs to be
checked, e.g.

  @MyRolesChecker("username", "myole");
  public String get() { ... }

Paul.


public class RolesAllowedResourceFilterFactory implements
ResourceFilterFactory {

     private @Context SecurityContext sc;

     private class Filter implements ResourceFilter,
ContainerRequestFilter {

         private final boolean denyAll;
         private final String[] rolesAllowed;

         protected Filter() {
             this.denyAll = true;
             this.rolesAllowed = null;
         }

         protected Filter(String[] rolesAllowed) {
             this.denyAll = false;
             this.rolesAllowed = (rolesAllowed != null) ?
rolesAllowed : new String[] {};
         }

         // ResourceFilter

         public ContainerRequestFilter getRequestFilter() {
             return this;
         }

         public ContainerResponseFilter getResponseFilter() {
             return null;
         }

         // ContainerRequestFilter

         public ContainerRequest filter(ContainerRequest request) {
             if (!denyAll) {
                 for (String role : rolesAllowed) {
                     if (sc.isUserInRole(role))
                         return request;
                 }
             }

             throw new
WebApplicationException(Response.Status.FORBIDDEN);
         }
     }

     public List<ResourceFilter> create(AbstractMethod am) {
         // DenyAll on the method take precedence over RolesAllowed
and PermitAll
         if (am.isAnnotationPresent(DenyAll.class))
             return Collections.<ResourceFilter>singletonList(new
Filter());

         // RolesAllowed on the method takes precedence over PermitAll
         RolesAllowed ra = am.getAnnotation(RolesAllowed.class);
         if (ra != null)
             return Collections.<ResourceFilter>singletonList(new
Filter(ra.value()));

         // PermitAll takes precedence over RolesAllowed on the class
         if (am.isAnnotationPresent(PermitAll.class))
             return null;

         // RolesAllowed on the class takes precedence over PermitAll
         ra = am.getResource().getAnnotation(RolesAllowed.class);
         if (ra != null)
             return Collections.<ResourceFilter>singletonList(new
Filter(ra.value()));

         // No need to check whether PermitAll is present.
         return null;
     }
}

On Nov 20, 2009, at 5:07 AM, Robert Koberg wrote:

> Hi,
>
> Say I have a requested resource located at:
>
> /myapp/rest/accounts/{username}/state
>
> (/myapp/rest/* is handled by the jersey ServletContainer used as a
> filter)
>
> I want to ensure the user has the role admin or the username
> @PathParam equals the Principal's name.
>
> ((Every time I do the work, it has tended to be the long way around
> because later I find that there is a much more convenient/clean/
> elegant solution existing in Jersey.))
>
> What I am doing (which seems like the long way) is having the
> following in a superclass that gets extended by most of my rest
> pojos. So, I have a convenience 'isAuthorized' method that allows
> users with the role 'admin' through or users that have Principals
> whose name matches the uri template variable.
>
> Is there a better, jersey way of doing this?
>
>
> @Context SecurityContext security;
>
>
> protected boolean isAdmin() {
> return security.isUserInRole(adminRole);
> }
>
> protected boolean isTargetUser(String email) {
> return
> security.getUserPrincipal().getName().equalsIgnoreCase(email);
> }
>
> protected boolean isAuthorized(String email) {
> if (isTargetUser(email) || isAdmin()) {
> return true;
> }
> return false;
> }
>
> protected boolean isAuthorized(String email, String role) {
> ...
> }
>
> protected boolean isAuthorized(String email, List<String> roles) {
> ...
> }
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>