我有以下路线:
/projects/{projectName}
和
/projects/{projectName}/Wall/{wallName}
现在我希望允许所有GET,但PUT,POST,DELETE应该只允许项目成员,即该项目的用户成员。我有一个特殊的类,它给出了用户ID和项目名称,我可以获得用户成员资格的状态 - 类似于MyEnroler.getRole(userId, projectName)
- 其中userId是请求标头的一部分,而projectName
来自URI。
我尝试过很多东西但是没有用。这是个主意:
public class RoleMethodAuthorizer extends Authorizer {
@Override
protected boolean authorize(Request req, Response resp) {
//If it's a get request then no need for further authorization.
if(req.getMethod().equals(Method.GET))
return true;
else
{
String authorEmail = req.getClientInfo().getUser().getIdentifier();
String projectName = req.getAttributes().get("project").toString();
Role userRole = MyEnroler.getRole(authorEmail, projectName);
//forbid updates to resources if done by non-members of project
if(userRole.equals(MyEnroler.NON_MEMBER))
return false;
//for everybody else, return true
return true;
}
}
}
现在,在应用程序中创建入站根时,只需执行以下操作即可完成:
Router projectRouter = new Router(getContext());
RoleMethodAuthorizer rma = new RoleMethodAuthorizer();
//Guard declaration here. Then setNext Restlet
guard.setNext(projectRouter);
projectRouter.attach("/projects/{project}",rma);
Router wallRouter = new Router(getContext());
wallRouter.attach("/Wall/{wallName}", WallResource.class);
rma.setNext(wallRouter);
//return guard;
因此/projects/stackoverflow/Wall/restlet
的请求失败。永远不会找到该URL。我猜是因为它试图将它与projectRouter
匹配。好吧,我尝试了各种模式(MODE_BEST_MATCH or MODE_FIRST/NEXT_MATCH
)无济于事。
似乎没什么用。从概念上讲,这应该有效。我只是拦截一个电话,只是对请求透明,但不知道内部是如何工作的。
我可以在守卫之后移动授权人,但是我无法访问request attribute
projectName
- 我不想自己解析URL以搜索projectName,因为URL模式可能会改变并会破坏功能 - 即需要2次更改而不是一次。
任何想法如何实现这一目标?
答案 0 :(得分:2)
我会使用标准的RoleAuthorizer类来提供允许的角色列表,并且您的自定义注册器可能会分成两部分,然后我会添加一个自定义的Filter类来执行类似的操作来调用您的Enrolers。
protected int beforeHandle(final Request request, final Response response) throws ResourceException {
final String projectName = (String) request.getAttributes().get("projectName");
// Check that a projectName is supplied, should not have got this far otherwise but lets check.
if (projectName == null || projectName.isEmpty()) {
throw new ResourceException(Status.CLIENT_ERROR_NOT_FOUND);
}
if (Method.GET.equals(request.getMethod())){
new ReadEnroler(projectName).enrole(request.getClientInfo());
}else{
new MutateEnroler(projectName).enrole(request.getClientInfo());
}
return super.beforeHandle(request, response);
}
然后,当调用enrole时,enrolers会在clientInfo.getRoles()Collection中设置适当的值。