2

J'ai des difficultés à saisir l'idée d'autorisation dans PlayFramework (version 2.5). Ma situation est que j'ai une méthode API REST getUser et je veux restreindre son accès en effectuant une autorisation avec un jeton qui vient dans l'en-tête de demande personnalisé nommé "X-Authorization". Maintenant, mon code du contrôleur ressemble que:Restriction de l'accès à la méthode dans Play Framework avec autorisation - Java

package controllers; 

import models.User; 
import org.bson.types.ObjectId; 
import play.mvc.*; 
import org.json.simple.*; 
import views.html.*; 

public class ApiController extends Controller { 

    public Result getUser(String userId) { 

     User user = User.findById(new ObjectId(userId)); 
     JSONObject userG = new JSONObject(); 

     //Some code to append data to userG before return 
     return ok(userG.toJSONString()); 
    } 
} 

L'URL de l'itinéraire est défini comme suit:

GET /api/user/:id controllers.ApiController.getUser(id) 

Option 1 pourrait être de vérifier le jeton d'autorisation dans la méthode getUser et vérifier aussi pour d'autres informations d'identification, mais je veux restreindre l'accès avant même d'obtenir des appels méthode getUser. Comme à l'avenir j'ajouterai plus d'appels de méthode à cette API REST. Je vais donc réutiliser la même autorisation pour ces futures API REST. J'ai trouvé authorization disponible dans Play Framework que je ne comprends pas. J'ai essayé de mettre en œuvre l'autorisation par l'extension de la classe Security.Authenticator et les méthodes prépondérants getUserName et onUnauthorized comme ceci:

package controllers; 

import models.Site; 
import models.User; 
import org.json.simple.JSONObject; 
import play.mvc.Http.Context; 
import play.mvc.Result; 
import play.mvc.Security; 

public class Secured extends Security.Authenticator { 
    @Override 
    public String getUsername(Context ctx) { 
     String auth_key = ctx.request().getHeader("X-Authorization"); 
     Site site = Site.fineByAccessKey(auth_key); 

     if (site != null && auth_key.equals(site.access_key)) { 
      return auth_key; 
     } else { 
      return null; 
     } 
    } 

    @Override 
    public Result onUnauthorized(Context ctx) { 

     JSONObject errorAuth = new JSONObject(); 
     errorAuth.put("status", "error"); 
     errorAuth.put("msg", "You are not authorized to access the API"); 

     return unauthorized(errorAuth.toJSONString()); 
    } 
} 

J'ai joint en annexe l'annotation à la méthode getUser avec @Security.Authenticated(Secured.class). Cela fonctionne correctement et renvoie une erreur non autorisée. Mais maintenant je ne suis pas sûr si c'est la manière préférée. Je pense que ce n'est pas la bonne façon de le faire comme le nom de l'override de la fonction getUsername le suggère aussi. Je ne vérifie pas pour un nom d'utilisateur dans la session ou le cookie plutôt que le jeton présent dans l'en-tête de la demande.

Aussi je sais qu'il y a un module nommé Deadbolt qui est utilisé pour l'autorisation mais je lis ses documents et je ne suis pas capable de l'intégrer. C'était une intégration relativement complexe pour un débutant comme moi. J'étais confus sur la façon de l'utiliser. J'ai pensé à utiliser l'autorisation du contrôleur SubjectPresent mais je n'ai pas réussi à l'implémenter avec succès. En fin de compte, que suggérez-vous que devrais-je utiliser Security.Authenticator comme j'ai implémenté? Ou suggérez-vous que je passe à ma première option qui vérifie l'autorisation à l'intérieur de la méthode getUser? Ou Tout le monde peut me dire comment implémenter Deadbolt dans mon scénario?

+0

Juste pour tous ceux qui veulent savoir comment mettre en œuvre 'Security.Authenticated'. J'ai trouvé ce bon article suivant qui pourrait être une bonne aide: https://alexgaribay.com/2014/06/16/authentication-in-play-framework-using-java/ – Seeker

Répondre

2

Vous mélangez Autorisation et Authentification.

Voici un bon fil: Authentication versus Authorization

J'aime cette réponse:

Authentification = login + mot de passe (qui vous êtes)

Autorisation = autorisations (ce que vous sont autorisés à faire)

Authentification == Autorisation (à l'exception de l'utilisateur anonyme) si vous autorisez à faire quelque chose pour tous les utilisateurs que vous connaissez (c.-à-d.authentifiées utilisateurs)

L'objectif principal de Deadbolt est Autorisation (utilisateurs déjà authentifiés). Votre objectif principal est Authentification.

Je vous conseille d'utiliser Pac4J, il Authentification bibliothèque non seulement pour Play, et il a des versions pour Java comme pour Scala. Il y a un bon exemple de projet: https://github.com/pac4j/play-pac4j-java-demo

J'utilise moi-même bibliothèque dans mes projets et la tâche

Comme à l'avenir je vais ajouter plus des appels de méthode à ce api REST. Donc, je vais réutiliser la même autorisation pour les futures APIs REST que ainsi que .

je résous aussi facile que d'ajouter la configuration dans le « application.conf`:

pac4j.security { 
    rules = [ 
    {"/admin/.*" = { 
     authorizers = "ADMIN" 
     clients = "FormClient" 
    }} 
    ] 
} 

Il suffit de ne pas oublier d'ajouter le filtre de sécurité. Cette fonctionnalité présente dans le projet d'exemple, il suffit donc de cloner et d'essayer.

Une autre forme d'exemple the official page:

pac4j.security.rules = [ 
    # Admin pages need a special authorizer and do not support login via Twitter. 
    {"/admin/.*" = { 
    authorizers = "admin" 
    clients = "FormClient" 
    }} 
    # Rules for the REST services. These don't specify a client and will return 401 
    # when not authenticated. 
    {"/restservices/.*" = { 
    authorizers = "_authenticated_" 
    }} 
    # The login page needs to be publicly accessible. 
    {"/login.html" = { 
    authorizers = "_anonymous_" 
    }} 
    # 'Catch all' rule to make sure the whole application stays secure. 
    {".*" = { 
    authorizers = "_authenticated_" 
    clients = "FormClient,TwitterClient" 
    }} 
] 
+0

Merci pour les précisions sur l'authentification et l'autorisation. Je vais regarder dans le module pac4j. – Seeker