Thanks - that's perfect.
-Rob
On Nov 20, 2009, at 3:12 AM, Paul Sandoz wrote:
> 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
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>