【问题标题】:Jersey declarative linking permissions using RolesAllowedJersey 声明性链接权限使用 RolesAllowed
【发布时间】:2017-06-01 13:04:04
【问题描述】:

我想将 Jersey 的 DeclarativeLinking 功能与其 RolesAllowed 功能结合起来。

我能够成功地将链接注入到响应中,但该注入不注意该端点的 RolesAllowed 注释。

例如,假设有两个用户。称他们为管理员和用户。两者都可以访问 GET 资源,但只有管理员可以访问 DELETE。

如果资源方法受@RolesAllowed 保护,那么我希望没有该角色的用户不会注入该端点。情况似乎并非如此。

我已按照here 找到的示例进行操作。

以下是我正在进行的项目的简化版本,用于说明目的。

对于管理员,我希望得到以下 json,

{
    "id" : 1
    "value" : "someValue",
    "links" : [
        {
            "href": "http://localhost/context/model/1",
            "rel": "self",
            "type": "GET"
        },
        {
            "href": "http://localhost/context/model/1",
            "rel": "delete",
            "type": "DELETE"
        },
    },
}

这正是我得到的。不幸的是,对于没有访问该端点所需的正确角色的用户,我也收到了此响应。仍会为用户提供指向删除端点的链接,但由于 RolesAllowed,该用户将收到 403。

型号

public class Model {

private int id;
private String value;
//constructor/getters/setters

模型表示

public class ModelRep {
    @XmlPath(".") //Allows me to flatten json so that links and document are at the same level
    private Model model;

    @InjectLinks({
        @InjectLink(
            rel = "self",
            type = "GET",
            resource = ModelResource.class,
            method = "getModel",
            bindings = @Binding(name = "id", value = "${instance.id}"),
            style = Style.ABSOLUTE
        ),
        @InjectLink(
            rel = "delete",
            type = "DELETE",
            resource = ModelResource.class,
            method = "deleteModel",
            bindings = @Binding(name = "id", value = "${instance.id}"),
            style = Style.ABSOLUTE
        )
    })
    @XmlJavaTypeAdapter(LinkAdapter.class)
    private List<Link> links;
    //constructor/getters/setters

模型资源

@Path("/model")
@Produces(MediaType.APPLICATION_JSON)
public class ModelResource {

    @GET
    @Path("/{id}")
    public Response getModel(@PathParam("id") int id) {
        Model m = dao.get(id);
        ModelRep mr = new modelRep(m);
        GenericEntity<ModelRep> ent = new GenericEntity<ModelRep>(mr) {};
        return Response.status(Status.OK).entity(ent);
    }

    @DELETE
    @Path("/{id}")
    @RolesAllowed(Roles.ADMIN)
    public Response deleteModel(@PathParam("id") int id) {
        dao.delete(id);
        return Response.status(Status.NO_CONTENT);
    }

问题 有没有什么方法可以基于 RolesAllowed 实现条件声明性链接?

我知道 InjectLink 注释存在一个条件子句,但允许的值是实例 (ModelRep)、实体(我认为是响应对象?)、资源 (ModelResource)。

我不知道有什么方法可以使用这些来检查权限。

非常感谢任何建议

【问题讨论】:

    标签: java rest jersey jax-rs hateoas


    【解决方案1】:

    所以我最终找到了一个有点笨拙但效果很好的解决方案。

    每个资源都扩展了一个基础资源类

    @Path("/model")
    @Produces(MediaType.APPLICATION_JSON)
    public class ModelResource extends BaseResource {
    

    BaseResource 定义了一个公共方法,该方法返回当前资源的特定方法是否受到 RolesAllowed 注解的限制。

    public abstract class BaseResource {
    
        @Context
        private SecurityContext security;
    
        public boolean isMethodRoleProtected(String sMethod) {
            Method[] methods = this.getClass().getDeclaredMethods();
            for (Method m : methods) {
                if (m.getName().equalsIgnoreCase(sMethod)) {
                    Annotation[] annotations = m.getAnnotations();
                    for (Annotation a : annotations) {
                        if (a instanceof RolesAllowed) {
                            String[] roles = ((RolesAllowed) a).value;
                            return userHasRole(roles);
                        }
                    }
                }
            }
            return false;
        }
    
        protected boolean userHasRole(String... roles) {
            for (String role : roles) {
                if (security.isUserInRole(role)) {
                    return true;
                }
            }
            return false;
        }
    }
    

    最后,InjectLink 注解将如下所示,

    @InjectLink(
        rel = "self",
        type = "GET",
        resource = SomeResource.class,
        method = "someMethod",
        bindings = @Binding(name = "id", value = "${instance.id}"),
        style = Style.ABSOLUTE,
        condition = "${resource.isMethodRoleProtected(someMethod)}"
    ),
    

    'resource' 是扩展 BaseResource 的当前端点类的实例。因此,仅当当前用户具有该方法的 RolesAllowed 注释中存在的角色时,才会注入此链接。

    此解决方案需要实现 SecurityContext。

    如果其他人有更好/更清洁的解决方案或改进我找到的解决方案的方法,我仍然很乐意听到并会相应地调整接受的答案。干杯

    【讨论】:

      猜你喜欢
      • 2012-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-15
      • 1970-01-01
      相关资源
      最近更新 更多