Fine authentication with RESTlet

I want to open a resource using a RESTlet with small-scale authentication. My ServerResource should be accessible through GET only for authenticated members (using BASIC Authentication). However, POST requests should also be available to callers without any authentication.

To clear: http: // path / myapp / user must allow anyone to register using POST , but only registered members should be able to GET list of all users.

Unfortunately, I don’t really like RESTlet, and I only find examples using more rude authentication for whole Restlet or Router s.

So, how to enable additional authentication for resources and check them at the level of each method?

Thanks in advance!

+7
java authentication restlet
source share
2 answers

In order to perform basic authentication in RESTlet 2.0 (I assume you are using 2.0 since you mention ServerResource ) you need to use the ChallengeAuthenticator . If this is configured using optional = true , then authentication will only be requested when calling ChallengeAuthenticator.challenge() .

You can create your application using the authenticate() method and call it when you need access to the resource that you want to protect:

Application:

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

Resource:

 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 // ... } } 
+15
source share

I am currently using Restlet v2.0.10.

The problem with ChallengeAuthenticator.isOptional() is that it is all or nothing. An alternative to the answer above in @ sea36 is to override ChallengeAuthenticator.beforeHandle() to authenticate or skip it based on the request method. For example, the resource below will only ask for authentication when the GET method is used.

Application:

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

Resource:

 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 // ... } } 

Please note: this example applies the authentication policy in GET only to UserResource , and not to other resources handled by the router.

+5
source share

All Articles