2011-07-09 34 views
10

/users/{id}成为RESTful服务中的资源URL。RESTful服务中的资源级别授权

启用基本身份验证,只有经过身份验证的用户才可以访问该URL。

示例方案:

User_1 & User_2被认证与用户id用户1 & 2. 由于两个被认证,两者都被具有访问,

  • /users/1
  • /users/2

但期望是User_1应该有权访问/users/1而不是/users/2或其他userId。

问题: 如何在RESTful服务中进行资源级别授权?

注:我使用的JAX-RS(与Apache CXF实现)实现基于REST的,有益的,如果你能与JAX-RS解释。

-Barath

编辑:

正如多纳尔提到的,我不是在寻找基于角色的授权,而资源级别的授权。

举个例子,让我们说/用户/ {ID} /照片/ {} PHOTOID是另一个资源的URL。用户1只能访问属于他的照片。如果2 PHOTOID属于user_2,那么当一个请求/用户1 /照片/请/ 2,我们应该给http_404错误代码USER_1。[由于USER_1也被验证的用户,他可以调用/用户/ /照片/ 2,所以我们必须基于不是通过资源URL]

只有我能想到的是解决方案,包括唯一的ID,它确定在每个查询,如鉴权认证参数标识的用户ID,

而不是SELECT * FROM PHOTO_TBL WHERE PHOTO_ID=2;

使用SELECT * FROM PHOTO_TBL, USER_TBL WHERE PHOTO_ID=2 AND USER_ID=1 AND USER_ID=PHOTO_ID;

使用此资源的

正在传递属于特定用户的数据。 [有应防止在客户端的唯一ID,其被用于在授权决定(在此情况下用户id)的变形的机构,因为所有的请求都是无状态的请求]

警告:每个查询应该足够聪明以了解安全问题并包含额外的加入。这是一个糟糕的设计,将安全逻辑与每个业务功能联系在一起。

我还没有寻找到春天的安全性,以及它如何在这种使用情况下使用。

+0

就像你在标签中说明的那样,这是过去认证时的授权问题。这可以在应用程序中实现,也可以作为比较URL中和验证标头中的用户标识的中介代理来实现。 – Szocske

+0

@Szocske:这是值得把它放在应用程序中的地方。但是你可以使用Spring AOP(和Spring Security)来使它更容易。唯一稍微棘手的一点是意识到这实际上不是基于角色的访问控制,所以SpringSec的RBAC支持并不相关。 (唉,这就是最好的教程材料...) –

+0

好吧,现在我看到编辑图片ID,无论如何需要加入到用户表。然而,在这种情况下,URL中的用户标识很少需要:-) – Szocske

回答

3

我建议没有在URL中的用户ID(好像它是“有限”由基本身份认证报头,那么你可能也只是有它由基本身份验证头“指定”)。这将减少引入直接对象引用漏洞的风险 - https://www.owasp.org/index.php/Top_10_2010-A4-Insecure_Direct_Object_References

在这种情况下,你可以有以下URL之一:

/users/CURRENT 
/me 

由于照片是子资源,那么你可以只创建在用户中使用“序列号”照片。在sql数据库中,这意味着在用户和照片列上都有一个“复合键”。

/users/CURRENT/photo/{user_photo_seq} 
/me/photo/{user_photo_seq} 

你的SQL然后将类似:

SELECT * FROM PHOTO_TBL WHERE USER_ID=<BasicAuthUsername> AND PHOTO_ID=<path param value>; 

“基本身份验证头” 的一个很好的解释:

http://en.wikipedia.org/wiki/Basic_access_authentication

+0

你能解释一下Basic Auth标题是什么吗? –

1

JAX-RS specifies sub-resource那里而不是在一个方法处理请求,处理委托给其他对象 - 子资源。

使用子资源足以照顾根资源,并且嵌套子资源也将得到保护。

在该示例中,您可以看到UserResource及其所有子资源,仅供授权用户使用。

@Path("/user/{userId}") 
public class UserResource { 

    private final String userId; 

    public UserResource(@PathParam("userId") String userId, @Context SecurityContext securityContext) { 
    this.userId = userId; 

    boolean authorized = /* authorization code */; 

    if (!authorized) { throw new WebApplicationException(Status.UNAUTHORIZED); } 
    } 

    @Path("photo") 
    public PhotoResource getPhotoResource() { 
    return new PhotoResource(userId); 
    } 

} 

public class PhotoResource { 

    private final String userId; 

    public PhotoResource(String userId) { 
    this.userId = userId; 
    } 

    @GET 
    public Response listAll() { /* ... */ } 

    @GET 
    @Path("{photoId}") 
    public Response present() { /* ... */ } 

}