使用 RolesAllowed 的 Jersey 声明链接权限
Jersey declarative linking permissions using RolesAllowed
我想将 Jersey 的 DeclarativeLinking 功能与其 RolesAllowed 功能相结合。
我能够将 links 成功注入到响应中,但该注入没有注意到该端点的 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"
},
},
}
这正是我得到的。不幸的是,对于没有访问该端点所需的正确角色的用户,我也会收到此响应。用户仍将获得删除端点的 link,但由于 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 实现条件声明 linking 吗?
我知道 InjectLink 注释存在条件子句,但允许的值为实例 (ModelRep)、实体(我认为是响应对象?)、资源 (ModelResource)。
我不知道使用其中任何一个来检查权限的方法。
非常感谢任何建议
所以我最终找到了一个有点老套但效果很好的解决方案。
每个资源扩展一个基础资源类
@Path("/model")
@Produces(MediaType.APPLICATION_JSON)
public class ModelResource extends BaseResource {
BaseResource 定义了一个 public 方法,该方法 returns 当前资源的特定方法是否受 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 的当前端点 class 的实例。因此,仅当当前用户具有该方法的 RolesAllowed 注释中存在的角色时,才会注入此 link。
此解决方案需要实施 SecurityContext。
如果其他人有 better/cleaner 解决方案或改进我找到的解决方案的方法,我仍然很乐意听到并会相应地调整接受的答案。干杯
我想将 Jersey 的 DeclarativeLinking 功能与其 RolesAllowed 功能相结合。
我能够将 links 成功注入到响应中,但该注入没有注意到该端点的 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"
},
},
}
这正是我得到的。不幸的是,对于没有访问该端点所需的正确角色的用户,我也会收到此响应。用户仍将获得删除端点的 link,但由于 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 实现条件声明 linking 吗?
我知道 InjectLink 注释存在条件子句,但允许的值为实例 (ModelRep)、实体(我认为是响应对象?)、资源 (ModelResource)。
我不知道使用其中任何一个来检查权限的方法。
非常感谢任何建议
所以我最终找到了一个有点老套但效果很好的解决方案。
每个资源扩展一个基础资源类
@Path("/model")
@Produces(MediaType.APPLICATION_JSON)
public class ModelResource extends BaseResource {
BaseResource 定义了一个 public 方法,该方法 returns 当前资源的特定方法是否受 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 的当前端点 class 的实例。因此,仅当当前用户具有该方法的 RolesAllowed 注释中存在的角色时,才会注入此 link。
此解决方案需要实施 SecurityContext。
如果其他人有 better/cleaner 解决方案或改进我找到的解决方案的方法,我仍然很乐意听到并会相应地调整接受的答案。干杯