【发布时间】:2017-08-18 16:41:08
【问题描述】:
我已经构建了一个 EmployeeEndpoint,它包含不同的方法,例如创建、更新、删除等等。为了简化这个问题,我只使用了 create 方法。
因为我想要一个可扩展的应用程序,所以我构建了一个包含基本方法的接口。在界面中,我现在可以使用 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);
}
}
但解决方案 1 不是一个好主意,因为并非每个实体都只能由管理员创建。使用解决方案 2 我失去了可扩展性和注释代码更少的优势。所以最好的方法是:
解决方案 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 接口方法(称为 filter)中捕获 Permissions-Annotation 时,我得到了 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
}
是否有可能采用解决方案 3 或我具有相同优势的不同方法?
更新
因为原因似乎不是我发布的代码,所以我将向您展示我的 AuthorizationFilter。因此我使用了this 发帖。
授权过滤器
@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");
}
}
}
【问题讨论】:
-
“根本不考虑权限”是什么意思?
-
当我在名为 filter 的 JAX-RS 的 ContainerRequestFilter 接口方法中捕获 Permissions-Annotation 时,我得到了
null的值。 -
刚刚测试过,它工作正常。您收到 NullPointerException 还是调用结果为 null?
-
调用结果为null。
标签: java interface annotations jax-rs