2017-08-18 35 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”这是一个好主意,因为不是每个实体都可以创建o只有一位管理员。并与解决方案我放弃了可扩展性的优势和更少的注释代码。所以最好的办法是:

解决方案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的价值,我不明白。

@Context 
private ResourceInfo resourceInfo; 

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

注释

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

枚举

public enum Role { 
    Admin, 
    User 
} 

是否有可能以任何方式去解决或不同的方法,我得到同样的效果?

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时,我会看到'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