如何使用 Restlet 在"middle of the URL"中添加过滤器?



我有以下路线:

/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),但没有成功。

似乎什么都不管用。从概念上讲,这应该有效。我只是拦截了一个电话,对请求保持透明,但不知道内部情况如何。

我可以在保护之后移动授权人,但我会失去对projectNamerequest attribute的访问权限-我不想自己解析URL来搜索projectName,因为URL模式可能会更改并破坏功能-即需要2次更改而不是1次。

有什么想法可以实现吗?

我会使用标准的RoleAuthorizer类来提供允许的角色列表,以及您的自定义注册者,可能会分成两个。然后我会添加一个自定义Filter类来调用您的注册者。

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);
}

当调用enrolle时,注册者将在clientInfo.getRoles()集合中设置适当的值。

最新更新