Pergunta

eu quero expor um recurso usando Restlet com uma autenticação de grão fino. Meu ServerResource deve ser acessível via GET apenas para membros autenticados (usando a autenticação básica). No entanto, os pedidos usando POST deve estar disponível também para chamadores sem qualquer autenticação.

Para clearify: http: // path / myapp / user deve permitir que alguém se registrar usando POST, mas Somente usuários registrados deve ser capaz de GET uma lista de todos os usuários.

Eu sou, infelizmente, não muito em Restlet e eu só encontrar exemplos usando a autenticação mais grossa para Restlets inteiros ou Routers.

Então, como faço para habilitar a autenticação opcional para recursos e vê-los em um nível por método?

Agradecemos antecipadamente!

Foi útil?

Solução

Para fazer a autenticação básica em Restlet 2.0 (eu suponho que você está usando 2.0, desde que você menciona ServerResource), você precisa usar um ChallengeAuthenticator. Se este é configurado com optional = true a autenticação só será solicitado se você invocar ChallengeAuthenticator.challenge().

Você pode criar seu aplicativo com um método authenticate(), e chamar isso sempre que você precisa ter acesso a um recurso a ser protegido:

aplicação:

package example;

import org.restlet.*;
import org.restlet.data.ChallengeScheme;
import org.restlet.routing.Router;
import org.restlet.security.*;

public class ExampleApp extends Application {

    private ChallengeAuthenticator authenticatior;

    private ChallengeAuthenticator createAuthenticator() {
        Context context = getContext();
        boolean optional = true;
        ChallengeScheme challengeScheme = ChallengeScheme.HTTP_BASIC;
        String realm = "Example site";

        // MapVerifier isn't very secure; see docs for alternatives
        MapVerifier verifier = new MapVerifier();
        verifier.getLocalSecrets().put("user", "password".toCharArray());

        ChallengeAuthenticator auth = new ChallengeAuthenticator(context, optional, challengeScheme, realm, verifier) {
            @Override
            protected boolean authenticate(Request request, Response response) {
                if (request.getChallengeResponse() == null) {
                    return false;
                } else {
                    return super.authenticate(request, response);
                }
            }
        };

        return auth;
    }

    @Override
    public Restlet createInboundRoot() {
        this.authenticatior = createAuthenticator();

        Router router = new Router();
        router.attach("/user", UserResource.class);

        authenticatior.setNext(router);
        return authenticatior;
    }

    public boolean authenticate(Request request, Response response) {
        if (!request.getClientInfo().isAuthenticated()) {
            authenticatior.challenge(response, false);
            return false;
        }
        return true;
    }

}

recursos:

package example;

import org.restlet.data.MediaType;
import org.restlet.representation.EmptyRepresentation;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.ServerResource;

public class UserResource extends ServerResource {

    @Override
    public Representation get() {
        ExampleApp app = (ExampleApp) getApplication();
        if (!app.authenticate(getRequest(), getResponse())) {
            // Not authenticated
            return new EmptyRepresentation();
        }

        // Generate list of users
        // ...
    }     

    @Override
    public Representation post(Representation entity) {
        // Handle post
        // ...
    }

}

Outras dicas

Eu estou usando no momento Restlet v2.0.10.

O problema com ChallengeAuthenticator.isOptional() é que é tudo ou nada. Uma alternativa para a resposta fornecida pelo @ sea36 acima é substituir ChallengeAuthenticator.beforeHandle(), quer executar a autenticação ou pule baseado no método de solicitação. Por exemplo, o recurso abaixo só irá exigir autenticação quando o método GET é usado.

aplicação:

package example;

import org.restlet.*;
import org.restlet.data.ChallengeScheme;
import org.restlet.routing.Router;
import org.restlet.security.ChallengeAuthenticator;
import org.restlet.security.MapVerifier;

public class ExampleApp extends Application {

    private ChallengeAuthenticator createAuthenticator() {
        Context context = getContext();
        ChallengeScheme challengeScheme = ChallengeScheme.HTTP_BASIC;
        String realm = "Example site";

        // MapVerifier isn't very secure; see docs for alternatives
        MapVerifier verifier = new MapVerifier();
        verifier.getLocalSecrets().put("user", "password".toCharArray());

        ChallengeAuthenticator authOnGet = new ChallengeAuthenticator(context, challengeScheme, realm) {
            @Override
            protected int beforeHandle(Request request, Response response) {
                if (request.getMethod() == Method.GET)
                    return super.beforeHandle(request, response);

                response.setStatus(Status.SUCCESS_OK);
                return CONTINUE;
            }
        };

        return authOnGet;
    }

    @Override
    public Restlet createInboundRoot() {
        ChallengeAuthenticator userResourceWithAuth = createAuthenticator();
        userResourceWithAuth.setNext(UserResource.class);

        Router router = new Router();
        router.attach("/user", userResourceWithAuth);

        return router;
    }

}

recursos:

package example;

import org.restlet.resource.Get;
import org.restlet.resource.Post;
import org.restlet.representation.Representation;
import org.restlet.resource.ServerResource;

public class UserResource extends ServerResource {

    @Get
    public Representation listUsers() {
        // retrieve list of users and generate response
        // ...
    }     

    @Post
    public void register(Representation entity) {
        // handle post
        // ...
    }
}

Note que este exemplo aplica a política de autenticar em GET apenas ao UserResource e não outros recursos manipulados pelo router.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top