有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Restlet方法和用户授权

我对Restlet和REST基本上是新手,希望为正在运行的服务器/数据库实现restfulapi。到目前为止,路由和寻址似乎工作正常,但我需要一些关于如何处理身份验证和授权的提示

情况:有些资源只有一些用户才能以某些方式与之交互。例如,User1可能可以获取资源,但不能放置任何内容,而User2可以同时执行这两项操作,User3甚至可能不读取资源,User4是唯一允许使用DELETE的

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

我如何授权特定用户只执行特定任务是否有方法组合授权人,或让他们执行多个测试?我必须写一个自定义授权人吗(我将如何做)

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


共 (1) 个答案

  1. # 1 楼答案

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

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

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

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

    {}的实现如下所示:

    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的实现如下所示:

    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请求中可用的角色,以确定是否允许经过身份验证的用户执行该方法:

    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,并按如下方式注册它:

        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的实现可以是这样的:

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

    希望对你有帮助, 蒂埃里