安全REST端点内部服务器错误中的多个角色

时间:2014-01-15 20:03:10

标签: java rest java-ee glassfish jax-rs

我有一个RESTful Web服务,我想在不同的端点上允许不同的角色。例如,我有以下类,其中两个方法一个用于访问管理员角色,另一个用于管理员角色访问。我正在使用Glassfish并设置了JDBCRealm,我创建了两个用户,每个角色一个。

@Stateless
@Path("testrole")
@DenyAll
public class TestRoleREST {

   @RolesAllowed("admin")
   @GET
   @Path("admin")
   @Produces("application/xml")
   public TestData getAdmin() {
      return new TestData("admin", 0);
   }

   @RolesAllowed("manager")
   @GET
   @Path("manager/{id}")
   @Produces("application/xml")
   public TestData getManager(@PathParam("id") Integer id){
      return new TestData("manager", id);
   }


   @XmlRootElement
   @XmlAccessorType(XmlAccessType.FIELD)
   public static class TestData{
      private String roleName;
      private int number;

      private TestData(){
      }

      public TestData(String roleName, int number){
         this.roleName = roleName;
         this.number = number;
      }
   }
}

在URI上使用curl:testrole / manager / 2按预期返回一些XML,在URI上也是如此:admin用户的testrole / admin。如果我不提供凭据,我会收到预期的HTTP 401 Not Authorized。

curl -X GET -H "Accept:application/xml" -H "Content-Type:application/xml" -u manager:test http://localhost/server/rest/testrole/manager/2

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<testData>
   <roleName>manager</roleName>
   <number>2</number>
</testData>

但是如果我在URI上使用curl:testrole / admin使用manager用户,那么我得到一个HTTP 500内部服务器错误,这是由javax.ejb.AccessLocalException: Client not authorized for this invocation引起的。

curl -X GET -H "Accept:application/xml" -H "Content-Type:application/xml" -u manager:test http://localhost/server/rest/testrole/admin

为什么经过身份验证的用户才会收到HTTP 401,403或其他一些正常的错误代码?有没有办法配置应用程序以返回首选的HTTP错误代码或我错过了一些配置?

抛出从RuntimeException继承的AccessLocalException似乎有点沉重,因为经过身份验证的用户尝试访问未经授权的URI。

这个问题(JPA Glassfish Database Update Issue)似乎处理同样的例外和原因,但我不明白它是如何,甚至是否与我的问题有关。在使用经过适当身份验证和授权的用户时,我有一项工作服务。

1 个答案:

答案 0 :(得分:0)

我在另一个有些无关的问题(JAX-RS — How to return JSON and HTTP status code together?)的答案中找到了我的问题的部分解决方案。答案是使用javax.ws.rs.ext.ExceptionMapper来掩盖客户端上的内部服务器异常。这仍然会导致在服务器上生成堆栈跟踪,但至少客户端不会暴露给HTTP 500代码。

mapper的代码很简单,它允许我在处理AccessLocalException时自定义响应。

@Provider
public class ApplicationExceptionMapper implements ExceptionMapper<AccessLocalException> {

   @Override
   public Response toResponse(AccessLocalException exception) {
      return Response.status(Response.Status.NOT_FOUND).build();
   }
}

正如我在开头所说,这是一个部分答案,因为我仍然认为服务器不应该为经过身份验证的用户访问未经授权的端点生成异常,但这可能是原始开发人员的意图。如果在配置REST端点上的角色方面存在另一个难题,以便不生成AccessLocalException,请分享。与此同时,我可以使用这个ExceptionMapper解决方案。