Feinkörnige Authentifizierung mit Restlet
-
19-09-2019 - |
Frage
Ich mag eine Ressource belichten. Mein ServerResource
sollte nur für authentifizierte Mitglieder (unter Verwendung von Standardauthentifizierung) über GET
zugänglich sein. Allerdings Anfragen POST
verwenden, sollten auch für Anrufer ohne Authentifizierung zur Verfügung.
Um clearify:
http: // path / myapp / Benutzer sollte jemand erlauben, registrieren POST
verwenden, aber nur registrierte Mitglieder sollten in der Lage sein GET
eine Liste aller Benutzer.
Ich bin leider nicht viel in Restlet und ich nur Beispiele mit gröberen Authentifizierung für ganzen Restlet
s oder Router
s finden.
Wie aktiviere ich optionale Authentifizierung für Ressourcen und überprüfen Sie sie auf einer pro-Methode Ebene?
Vielen Dank im Voraus!
Lösung
Standardauthentifizierung in Restlet 2.0 Um zu tun (ich nehme an, Sie verwenden 2.0, da Sie ServerResource
erwähnen), benötigen Sie einen ChallengeAuthenticator
verwenden. Wenn dies mit optional = true
konfiguriert ist, dann wird die Authentifizierung nur angefordert werden, wenn Sie ChallengeAuthenticator.challenge()
aufrufen.
Sie können Ihre Anwendung mit einer authenticate()
Methode erstellen und diese rufen, wenn Sie Zugriff auf eine Ressource müssen gesichert werden:
Anwendung:
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
// ...
}
}
Andere Tipps
Ich bin derzeit Restlet v2.0.10 verwendet wird.
Das Problem mit ChallengeAuthenticator.isOptional()
ist, dass es um alles oder nichts ist. Eine Alternative zu der Antwort, die von @ sea36 oben ist ChallengeAuthenticator.beforeHandle()
außer Kraft zu setzen, entweder Authentifizierung durchzuführen oder sie basierend auf Anforderungsverfahren zu überspringen. Zum Beispiel wird die Ressource unten nur eine Authentifizierung erforderlich, wenn die GET-Methode verwendet wird.
Anwendung:
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
// ...
}
}
Beachten Sie, dass dieses Beispiel die Politik der Authentifizierung auf GET gilt nur für die UserResource
und nicht andere vom Router behandelt Ressourcen.