首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >方法和用户的Restlet授权

方法和用户的Restlet授权
EN

Stack Overflow用户
提问于 2015-05-04 11:23:01
回答 1查看 760关注 0票数 2

一般来说,我对Restlet和REST都很陌生,我希望为运行中的服务器/数据库实现一个Restlet。到目前为止,路由和寻址似乎运行良好,但我需要一些关于如何处理身份验证和授权的提示。

情况:有一些资源,只有某些用户才能以某种方式进行交互。例如,User1可能可以获得资源,但不能放置任何东西,而User2可以两者都做,User3甚至可能不会读取,而User4是唯一允许使用DELETE的。

当然,MethodAuthorizer听起来很有希望,但它似乎只区分匿名用户和(所有)身份验证用户。另一个爪上的RoleAuthorizer不区分GET、PUT或其他请求方法,只区分资源。

我怎样才能授权某些用户只执行特定的任务呢?有没有办法组合授权器,或者让他们执行多个测试?我是否必须编写一个自定义授权程序(我将如何编写)?

另外,是否可以使用其他地方提供给身份验证者的凭据,例如将它们作为String传播到另一个方法?(如何)如何获得当前请求的标识符和秘密?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-05-04 11:53:01

事实上,我认为您应该利用Restlet的角色支持。事实上,Restlet提供了两个关于安全的附加元素:

  • Verifier,它根据请求中提供的凭据对用户进行身份验证。
  • Enroler,它加载身份验证用户的角色。

下面是一个基本身份验证的示例:

代码语言:javascript
复制
@Override
public Restlet createInboundRoot() {
    Router router = (...)

    Verifier verify = new MyVerifier(...);
    Enroler enroler = new MyEnroler(...);

    ChallengeAuthenticator guard = new ChallengeAuthenticator(getContext(),
            ChallengeScheme.HTTP_BASIC, "connector");
    guard.setVerifier(verifier);
    guard.serEnrole(enroler);
    guard.setNext(router);

    return guard;
}

Verifier的实现如下所示:

代码语言:javascript
复制
public class MyVerifier extends SecretVerifier {
    public int verify(String identifier, char[] secret)
                     throws IllegalArgumentException {
        ApplicationUser user = loadUser(identifier);
        //user contains both user hints and roles
        if (user!=null
              && compare(user.getPassword().toCharArray(), secret)) {
            Request request = Request.getCurrent();
            request.getClientInfo().setUser(user);
            return SecretVerifier.RESULT_VALID;
        } else {
            return SecretVerifier.RESULT_INVALID;
        }
    }
}

Enroler的实现如下所示:

代码语言:javascript
复制
public class MyEnroler implements Enroler {
    public void enrole(ClientInfo clientInfo) {
        Request request = Request.getCurrent();
        User user = request.getClientInfo().getUser();
        if (user!=null) {
            List<UserRole> roles = user.getRoles();
            if (roles!=null) {
                for (UserRole userRole : roles) {
                    // example of role creation
                    Role role = new Role(userRole.getName(), "");
                    clientInfo.getRoles().add(role);
                }
            }
        }
    }
}

然后,在资源中,您可以检查Restlet请求中可用的角色,以确定是否允许通过身份验证的用户执行该方法:

代码语言:javascript
复制
public MyServerResource extends ServerResource {
    private boolean hasRole(String expectedRole) {
        List<Role> roles = request.getClientInfo().getRoles();
        for (Role role : roles) {
            if (role.getName().equals(expectedRole)) {
                return true;
            }
        }
        return false;
    }

    private void checkRole(String role) {
        if (!hasRole(role)) {
            throw new ResourceException(
               Status.CLIENT_ERROR_FORBIDDEN);
        }
    }

    @Get
    public Representation getElement() {
        checkRole("read");
    }

    @Put
    public void updateElement(Representation repr) {
        checkRole("update");
    }

    @Delete
    public void deleteElement() {
        checkRole("delete");
    }
}

这种方法有点入侵性。您还可以根据所使用的HTTP方法和角色进行更一般的操作。为此,我们需要实现一个自定义Authorizer并按如下方式注册:

代码语言:javascript
复制
    Router router = (...)

    Authorizer authorizer = new MyAuthorizer();
    authorizer.setNext(router);

    Verifier verify = new MyVerifier(...);
    Enroler enroler = new MyEnroler(...);

    ChallengeAuthenticator guard = new ChallengeAuthenticator(getContext(),
            ChallengeScheme.HTTP_BASIC, "connector");
    guard.setVerifier(verifier);
    guard.serEnrole(enroler);
    guard.setNext(authorizer);

    return guard;
}

这个Authorizer的实现可以是这样的:

代码语言:javascript
复制
public class MyAuthorizer extends Authorizer {
    private String[] getRoles = new String[] { "read"};
    private String[] putRoles = new String[] { "update"};
    private String[] deleteRoles = new String[] { "delete"};

    private boolean hasRoles(String[] expectedRoles) {
        List<Role> roles = request.getClientInfo().getRoles();
        for (String expectedRole : expectedRoles) {
            for (Role role : roles) {
                if (role.getName().equals(expectedRole)) {
                    return true;
                }
            }
        }
        return false;
    }

    private void checkRoles(String[] roles) {
        if (!hasRole(roles)) {
            throw new ResourceException(
               Status.CLIENT_ERROR_FORBIDDEN);
        }
    }

    public boolean authorize(Request request, Response response) {
        if (!request.getClientInfo().isAuthenticated()) {
            throw new ResourceException(
               Status.CLIENT_ERROR_FORBIDDEN);
        }

        if ("GET".equals(request.getMethod().getName())) {
            checkRoles(getRoles);
        } else if ("PUT".equals(request.getMethod().getName())) {
            checkRoles(putRoles);
        } else if ("DELETE".equals(request.getMethod().getName())) {
            checkRoles(deleteRoles);
        }

        return false;
    }
}

希望它能帮到你,蒂埃里

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30028907

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档