2017-08-18 20 views
1

私は、作成、更新、削除などのさまざまなメソッドを保持するEmployeeEndpointを構築しました。この質問を簡略化するために、私はcreateメソッドを使用しました。Javaカスタムアノテーションは考慮されません

スケーラブルなアプリケーションが必要なので、基本メソッドを保持するインタフェースを構築しました。インターフェース内で、メソッドをJAX-RS-Annotationsで注釈を付けることができます。それらは継承されるので、私はEmployeeEndpoint内のインターフェースメソッドをオーバーライドするだけです。

インタフェース

public interface RESTCollection<T> { 
    @POST 
    @Consumes(MediaType.APPLICATION_JSON) 
    @Produces(MediaType.APPLICATION_JSON) 
    public T create(T entity) throws Exception; 
} 

エンドポイント

@Stateless 
@Path(“employee“) 
public class EmployeeEndpoint implements RESTCollection<Employee> { 
    @Override 
    public Employee create(Employee employee) throws Exception { 
     return this.createEmployee(employee); 
    } 
} 

は、上記の例では、正常に動作します。私はカスタムアノテーションを追加したい場合は私が行うことができます。

ソリューション1

public interface RESTCollection<T> { 
    @POST 
    @Consumes(MediaType.APPLICATION_JSON) 
    @Produces(MediaType.APPLICATION_JSON) 
    @Permissions(Role.Admin) 
    public T create(T entity) throws Exception; 
} 

または

ソリューション2

@Stateless 
@Path(“employee“) 
public class EmployeeEndpoint implements RESTCollection<Employee> { 
    @Override 
    @POST 
    @Consumes(MediaType.APPLICATION_JSON) 
    @Produces(MediaType.APPLICATION_JSON) 
    @Permissions(Role.Admin) 
    public Employee create(Employee employee) throws Exception { 
     return this.createEmployee(employee); 
    } 
} 

しかしソリューション ISN」すべてのエンティティを作成できるわけではないので、良いアイデアです管理者が管理します。そしてソリューションでは私はスケーラビリティの利点を失うし、注釈のコードは少なくなっています。だから、最良の方法は次のようになります。

ソリューション3

@Stateless 
@Path(“employee“) 
public class EmployeeEndpoint implements RESTCollection<Employee> { 
    @Override 
    @Permissions(Role.Admin) 
    public Employee create(Employee employee) throws Exception { 
     return this.createEmployee(employee); 
    } 
} 

しかし、私はフィルタと呼ばれるJAX-RS」ContainerRequestFilterインターフェイスメソッド内で権限アノテーションをキャッチしたときに、今、私は私nullの値を取得します理解していない。注釈

@NameBinding 
@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.METHOD, ElementType.TYPE}) 
public @interface Permissions { 
    Role[] value() default {}; 
} 

列挙

public enum Role { 
    Admin, 
    User 
} 

@Context 
private ResourceInfo resourceInfo; 

resourceInfo.getResourceMethod().getAnnotation(Permissions.class) // is null 

は、どのような方法で解決して行くことも可能です私は同じ利点を持っているまたは異なるアプローチ?

UPDATE

理由は、私はあなたに私のAuthorizationFilterが表示されます掲載のコードではないようですので。したがって、私はthisの投稿を使用しました。

AuthorizationFilter

@Provider 
@Priority(Priorities.AUTHORIZATION) 
public class AuthorizationFilter implements ContainerRequestFilter { 

    @Inject 
    @AuthenticatedUser 
    private User authenticatedUser; 

    @Context 
    private ResourceInfo resourceInfo; 

    @Override 
    public void filter(ContainerRequestContext requestContext) throws IOException { 

     Class<?> resourceClass = resourceInfo.getResourceClass(); 
     List<Role> classRoles = extractRoles(resourceClass); 

     Method resourceMethod = resourceInfo.getResourceMethod(); 
     List<Role> methodRoles = extractRoles(resourceMethod); 

     try { 

      if (methodRoles.isEmpty()) checkPermissions(classRoles, requestContext.getHeaderString(HttpHeaders.AUTHORIZATION)); 
      else checkPermissions(methodRoles, requestContext.getHeaderString(HttpHeaders.AUTHORIZATION)); 

     } catch (NotAuthorizedException e) { 
      requestContext.abortWith(
        Response.status(Response.Status.UNAUTHORIZED).build()); 
     } catch (Exception e) { 
      requestContext.abortWith(
        Response.status(Response.Status.FORBIDDEN).build()); 
     } 
    } 

    private List<Role> extractRoles(AnnotatedElement annotatedElement) { 
     if (annotatedElement == null) return new ArrayList<Role>(); 
     else { 
      Permissions perms = annotatedElement.getAnnotation(Permissions.class); 
      if (perms == null) return new ArrayList<Role>(); 
      else { 
       Role[] allowedRoles = perms.value(); 
       return Arrays.asList(allowedRoles); 
      } 
     } 
    } 

    private void checkPermissions(List<Role> allowedRoles, String authorizationHeader) throws NotAuthorizedException, Exception { 
     if (!allowedRoles.isEmpty()) { 
      if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) 
       throw new NotAuthorizedException("Authorization header must be provided"); 
      else if (!allowedRoles.contains(this.authenticatedUser.getRole())) 
       throw new Exception("User has no permissions"); 
     } 
    } 
} 
+2

「権限はまったく考慮されていません」とはどういう意味ですか? –

+0

JAX-RSのContainerRequestFilterインターフェイスメソッドのPermissions-Annotationをfilterという名前で捕捉すると、 'null'という値が得られます。 – Nadine

+0

ちょうどテストされ、それは正常に動作します。あなたはNullPointerExceptionを取得していますか、またはnullの呼び出しの結果ですか? –

答えて

0

あなたのコードはよさそうです。

私はいくつかのテストを実行していると私は考えることができる唯一の理由は、あなたのフィルター上のものよりも、あなたの従業員のリソース上の2異なるPermission種類を使用していることです。あなたのFilterコードに関する

わからない(あなたの輸入を確認してください)が、これは私が(輸入を参照)作業している次のとおりです。

package com.app.filters; // TODO change this with yours 

import java.io.IOException; 
import java.util.Arrays; 

import javax.ws.rs.container.ContainerRequestContext; 
import javax.ws.rs.container.ContainerRequestFilter; 
import javax.ws.rs.container.ResourceInfo; 
import javax.ws.rs.core.Context; 

import com.app.services.Permissions; // TODO change this with yours 

public class AuthorizationFilter implements ContainerRequestFilter { 

    @Context 
    ResourceInfo resourceInfo; 

    @Override 
    public void filter (ContainerRequestContext requestContext) throws IOException { 
     Permissions perms = resourceInfo.getResourceMethod().getAnnotation (Permissions.class); 

     System.out.println (getClass().getSimpleName() + " --> Permissions: " + Arrays.toString (perms.value())); // prints [Admin] 
    } 

} 

ボーナス、あなたは上の注釈の実際の値をテストする場合あなたの従業員のリソース:

.... 
import com.app.services.Permissions; // TODO change this with yours (the one on the filter being the same as this one) 
.... 

@Permissions (Role.Admin) 
@Override 
public Employee create (Employee employee) throws Exception { 
    Class<?> [] cArg = new Class [1]; 
    cArg [0]   = Employee.class; 

    Method method  = getClass().getMethod ("create", cArg); 
    Permissions perms = method.getAnnotation (Permissions.class); 

    System.out.println (EmployeeService.class.getSimpleName() + " --> Permissions: " + Arrays.toString (perms.value())); 

    return null; 
} 
+0

私は同じことを考えましたが、それはソリューション1と2がなぜ機能するのか説明しません。これはOPが実際に1と2でテストされたと仮定しています。 –

+0

あなたの答えをありがとう!それは輸入の問題ではなく、私のAuthorizationFilterはあなたとかなり似ています。しかし、私は質問を更新し、AuthorizationFilterを投稿しました。 – Nadine

関連する問題