如何保护REST资源,以便只有角色的单个用户可以访问它?

Zou*_*ire 5 security jersey realm java-ee

我已经成功地使用Jersey创建了一个REST Web服务,并通过java安全注释来保护它.它看起来像这样

GET    /users/     // gives me all users
GET    /users/{id} // gives the user identified by {id}
POST   /users/     // creates user
PUT    /users/{id} // updates user identified by {id}
DELETE /users/{id} // delete user
Run Code Online (Sandbox Code Playgroud)

我还设置了一个具有两个角色的领域:用户和管理员

我保护所有方法,以便只有管理员才能访问它们.

现在我想免费提供PUT /users/{id}GET /users/{id}方法,以便用户可以访问自己, 只有自己的资源.

例:

// user anna is logged in and uses the following methods
    GET    /users/anna // returns 200 OK
    GET    /users/pete // returns 401 UNAUTHORIZED
Run Code Online (Sandbox Code Playgroud)

由于我找不到通过注释配置它的方法,我正在考虑将HTTP请求传递给相应的方法以检查是否允许用户访问资源.

对于该GET /users/{id}方法,它看起来像这样:

@GET
@Path("/users/{id}")
@RolesAllowed({"admin","user"})
@Produces(MediaType.APPLICATION_JSON)
public Response getUser(
    @PathParam("id") String id,
    @Context HttpServletRequest req
) {
    HttpSession session = request.getSession(false);

    if (session != null && session.getValue("userID").equals(id))
        return getObject(User.class, id);

    return Response.status(Status.UNAUTHORIZED).build();
}
Run Code Online (Sandbox Code Playgroud)

我不喜欢这种方法,因为我认为我必须userID在会议中添加manualy.

  • 你知道更优雅的解决方法吗?

  • 如果不是,在使用表单身份验证时如何将userid添加到会话?

编辑

谢谢Will和Pavel :)这是我的最终解决方案:

@Context
private SecurityContext security;

// ...
@GET
@Path("/users/{id}")
@RolesAllowed({"admin","user"})
@Produces(MediaType.APPLICATION_JSON)
public Response getUser(@PathParam("id") String id){
    if (security.isUserInRole("user"))
        if (security.getUserPrincipal().getName().equals(id))
            return getObject(User.class, id);
        else
            return Response.status(Status.UNAUTHORIZED).build();
    else
        return getObject(User.class, id);
}
Run Code Online (Sandbox Code Playgroud)