Format REST de connexion utilisateur

13

Quelqu'un a-t-il une connexion REST fonctionnelle sur Drupal 8?

Voilà ce que j'ai essayé.

POST /user/login HTTP/1.1
Host: 8.d8.local
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: http://nikhilmohan.in
Cache-Control: no-cache

name=test&pass=password&form_id=user_login_form

Il me renvoie HTML au lieu de JSON .

niksmac
la source

Réponses:

15

À partir de 8.2, Drupal prend en charge les points de terminaison json pour l'authentification par cookie. Vous n'avez plus besoin de poster le formulaire 🎉

curl --header "Content-type: application/json" --request POST \
  --data '{"name":"admin", "pass":"admin"}' \
http://drupal.d8/user/login?_format=json

La sortie ressemblera

{"current_user":{"uid":"1","roles":["authenticated","administrator"],"name":"admin"},"csrf_token":"wBr9ldleaUhmP4CgVh7PiyyxgNn_ig8GgAan9-Ul3Lg","logout_token":"tEulBvihW1SUkrnbCERWmK2jr1JEN_mRAQIdNNhhIDc"}

Changement d'enregistrement: https://www.drupal.org/node/2720655

Autres méthodes d'authentification: https://www.drupal.org/docs/8/core/modules/rest/using-other-authentication-protocols

kalabro
la source
Je n'arrive pas à faire fonctionner cela, j'obtiens 403 "Cette route n'est accessible qu'aux utilisateurs anonymes." étrange car j'utilise REST évidemment pas connecté
jim smith
1
@jimsmith Qu'utilisez-vous pour tester l'appel? J'ai rencontré ce problème avant d'utiliser Postman car il recevait mes cookies Chrome et disait que j'étais connecté. Vous pouvez le tester en vous déconnectant dans le navigateur et en envoyant à nouveau la demande
Antero Duarte
11

Voici comment vous pouvez vous connecter via JavaScript pour Drupal 8 REST:

Drupal 8.2 et au-delà

  • POST :http://example.com/user/login?_format=json
  • Type de contenu :application/json
  • Données :{ "name": "admin", "pass": "myPassword" }
  • Réponse :200 OK

Cela se connectera correctement via l'authentification par cookie et retournera un résultat similaire à celui-ci:

{
  "current_user": {
    "uid":"1",
    "roles":["authenticated"],
    "name":"admin"
  },
  "csrf_token":"abc123",
  "logout_token":"def456"
}

J'ai créé un module contrib appelé jDrupal qui facilite la connexion avec JavaScript (entre autres):

// Login and show the user their id.
jDrupal.userLogin('admin', 'myPassword').then(function() {
  alert(jDrupal.currentUser().id());
});

Avant Drupal 8.2

  • POST :http://example.com/user/login
  • Type de contenu :application/x-www-form-urlencoded
  • Données :name=admin&pass=myPassword&form_id=user_login_form
  • Réponse :200 OK | 303 See Other

Vous enverrez les données dans l'URL sous forme de chaîne de requête. Le résultat sera HTML, donc il ne vous renverra rien d'utile, mais il se connectera correctement via l'authentification par cookie.

tyler.frankenstein
la source
Le retour du HTML est donc inévitable?
niksmac
À ce stade AFAIK, oui HTML est inévitable. J'imagine que cela s'améliorera avec le temps, car par exemple il n'y a pas encore de moyen d'enregistrer un utilisateur via REST, mais un problème a été fait.
tyler.frankenstein
cela ne fonctionne pas pour moi, est-il nécessaire d'utiliser également l'authentification de base?
Yusef
Pour info, JSON est renvoyé à partir de Drupal 8.2, donc plus aucun code HTML n'est renvoyé.
tyler.frankenstein
8
  1. Une demande HTTP n'est pas RESTful basée sur Content-Type.
  2. " Connexion REST " est techniquement un oxymore.

L'authentification RESTful signifie d'envoyer une authentification à chaque demande car elle est sans état. L'exemple fourni par Drupal 8 core est le module Basic Auth, qui permet d'envoyer des informations d'authentification pour une demande HTTP via l'authentification HTTP de base à un utilisateur autorisé à accéder au contenu via GET.

Exemple RESTful

Boucle: curl -vvv -k -H "Authorization: Basic test:password" http://8.d8.local/node/1?_format=json

GET /node/1?_format=json HTTP/1.1
Host: 8.d8.local
User-Agent: curl/7.43.0
Accept: */*
Authorization: Basic test:password

Cependant, ce n'est généralement pas suffisant. Les modules contrib simple_oauth et oauth fournissent respectivement la prise en charge OAuth 2 et 1, avec lesquels une requête HTTP peut être effectuée avec des jetons d'authentification OAuth basés sur les flux de travail OAuth décrits dans ces modules.

Mais la vraie question semble être

Comment me connecter via une API de services Web?

Il n'y a pas de module Drupal 8 stable pour le faire, mais le module Services fournit des méthodes pour créer des actions non RESTful et des actions ciblées telles que "connexion".

Ce qui suit fonctionne après avoir configuré un point de terminaison appelé "api":

Boucle: curl -vvv -k -H "Content-Type: application/json" -H "Accept: application/json" -d '{"username": "test", "password": "password"}' http://8.d8.local/api/user/login

POST /api/user/login HTTP/1.1
Host: 8.d8.local
Accept: application/json
Content-Type: application/json
Content-Length: 44

{"username": "test", "password": "password"}

Cela renvoie l'ID et le nom de la session JSON (également définis dans l'en-tête Set-Cookie de la réponse).

et vous pouvez également vous connecter avec l'appel ajax Jquery avec l'extrait suivant

$.ajax({
    url : "http://gttc.dd:8083/user/login",
    type : 'post',
    data : 'form_id=user_login_form&name=' + encodeURIComponent("username") + '&pass=' + encodeURIComponent("password"),
    dataType : 'json',
    error : function(data) {
            //error code
    },
    success : function(data) {
      console.log(data);
        //success code
    }
});
mradcliffe
la source
Les services semblent cool, mais le noyau Drupal est foiré dans D8 IMO. il y a encore beaucoup à venir.
niksmac
1
Depuis Drupal 8.2, vous pouvez (et devriez) utiliser la méthode décrite dans drupal.stackexchange.com/a/221045/13237
andeersg
4

Drupal Core Version: 8.x-4.x

Vous devez d'abord activer le service de connexion utilisateur, cela peut être accompli de nombreuses façons, je préfère utiliser le module d' interface utilisateur REST .

Accédez à / admin / config / services / rest et activez la ressource User Rest.

Une fois activé, vous pouvez accéder à / admin / config / services / rest / resource / entity% 3Auser / edit en cliquant sur Modifier à côté de la ressource utilisateur . Assurez-vous d'activer la méthode GET .

entrez la description de l'image ici

Maintenant que vous avez tout configuré, vous pouvez commencer à utiliser le service en exécutant cette commande dans le terminal ou en utilisant n'importe quelle application pour les requêtes curl comme: Postman et Restlet clients.

REMARQUE : le jeton CSRF peut être obtenu à partir de: / rest / session / token

curl -i -L -X POST \
  -H "Content-Type:application/json" \
  -H "Accept:application/json" \
  -H "X-CSRF-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
  -d \
     '{
       "name": "my_username",
       "pass": "my_password"
     }' \
'http://SITE-URL/user/login?_format=json'

Les objets de retour sont les suivants:

SUCCÈS :

{
  "current_user": {
  "uid": "1",
    "roles": [
      "authenticated"
    ],
    "name": "Admin"
  },
  "csrf_token": "bbbbbbbbbbbbbbbbbbbbbbbbbb",
  "logout_token": "ccccccccccccccccccccccccc"
}

ÉCHEC :

{
  "message":"Sorry, unrecognized username or password."
}
Mohammad AlQanneh
la source
> Accédez à / admin / config / services / rest et activez la ressource User Rest. Je pense que vous n'avez pas besoin d'activer la ressource utilisateur pour vous connecter avec l'api REST. L'activation de cette ressource n'est requise que si vous souhaitez effectuer une opération CRUD sur l'entité utilisateur. La connexion peut être obtenue avec l'api de repos comme mentionné par @ tyler.frankenstein
MutantMahesh
2

J'utilise une connexion RESTFul personnalisée sur drupal 8 mais pas avec un cookie. C'est pour une application mobile et chaque fois que j'ai besoin d'informations, j'utilise une simple authentification:

Depuis Drupal 8.2x, nous avons besoin de 2 fichiers dans un module:

rest.ressource.user.rest_ressource.yml dans le dossier config / install

langcode: en
status: true
dependencies:
  module:
    - basic_auth
id: user.rest_ressource
plugin_id: 'user_rest_ressource'
granularity: resource
configuration:
  methods:
    - GET
    - PATCH
  formats:
    - json
  authentication:
    - basic_auth

Vous pouvez ajouter plus de méthode comme DELETE / POST

Ensuite, nous avons besoin du fichier

userRestRessource.php dans src / Plugin / rest / resource

    <?php

    namespace Drupal\yourmodule\Plugin\rest\resource;

    use Drupal\Core\Session\AccountProxyInterface;
    use Drupal\rest\Plugin\ResourceBase;
    use Drupal\rest\ResourceResponse;
    use Symfony\Component\DependencyInjection\ContainerInterface;
    use Psr\Log\LoggerInterface;


    /**
     * Provides a resource to get view modes by entity and bundle.
     *
     * @RestResource(
     *   id = "user_rest_ressource",
     *   label = @Translation("User Rest"),
     *   uri_paths = {
     *     "canonical" = "/api/user/getInfo"
     *   }
     * )
     */
    class UserRestRessource extends ResourceBase {

      /**
       * A current user instance.
       *
       * @var \Drupal\Core\Session\AccountProxyInterface
       */
      protected $currentUser;

      /**
       * Constructs a Drupal\rest\Plugin\ResourceBase object.
       *
       * @param array $configuration
       *   A configuration array containing information about the plugin instance.
       * @param string $plugin_id
       *   The plugin_id for the plugin instance.
       * @param mixed $plugin_definition
       *   The plugin implementation definition.
       * @param array $serializer_formats
       *   The available serialization formats.
       * @param \Psr\Log\LoggerInterface $logger
       *   A logger instance.
       * @param \Drupal\Core\Session\AccountProxyInterface $current_user
       *   A current user instance.
       */
      public function __construct(
        array $configuration,
        $plugin_id,
        $plugin_definition,
        array $serializer_formats,
        LoggerInterface $logger,
        AccountProxyInterface $current_user) {
        parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger);

        $this->currentUser = $current_user;

      }

      /**
       * {@inheritdoc}
       */
      public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
        return new static(
          $configuration,
          $plugin_id,
          $plugin_definition,
          $container->getParameter('serializer.formats'),
          $container->get('logger.factory')->get('yourmodulename'),
          $container->get('current_user')
        );
      }

      /**
       * Responds to GET requests.
       *
       * Returns a list of bundles for specified entity.
       *
       * @throws \Symfony\Component\HttpKernel\Exception\HttpException
       *   Throws exception expected.
       */
      public function get() {

          $uid=$this->currentUser->getAccount()->id();
          $role=$this->currentUser->getAccount()->getRoles(1);

//here you can add your custom code
 $responseResource=new ResourceResponse(
          array()

      );
        return $responseResource;
      }

        /**
         * Responds to PATCH requests.
         *
         * Returns a list of bundles for specified entity.
         *
         * @throws \Symfony\Component\HttpKernel\Exception\HttpException
         *   Throws exception expected.
         */
        public function patch(){

        }

    }

N'oubliez pas d'aller au droit d'utilisateur pour accepter la méthode GET / POST ou tout ce que vous avez ajouté dans votre configuration.

Avec cela, vous pouvez créer chaque fichier REST personnalisé pour chaque entité personnalisée.

Et dans mon js: N'oubliez pas d'appeler

yoursiteUrl / rest / session / token

pour obtenir un jeton

$http({
            method: 'GET',
            url: 'siteUrl/api/user/getInfo?_format=json',
                          withCredentials:true,
                          headers: {
                                   'Content-Type': "application/hal+json",
                                   'X-CSRF-Token': token,
                                   'Authorization': 'Basic ' + btoa(user+':'+password),

                         },


                        }).then(function successCallback(response) {

                             return response;

                          }, function errorCallback(response) {
                              return false;

                          });
Kevin
la source
2

Suite à la réponse de @ tyler.frankenstein, si vous souhaitez mettre en place un formulaire de connexion avec Ajax, vous pouvez par exemple utiliser jQuery.

1. Obtenez un jeton CSRF

Nous devons faire une requête POST au user/loginpoint de terminaison de l'API Drupal 8. Ce point de terminaison (considéré comme une "méthode non sûre") nécessite que vous envoyiez un jeton CSRF.

La première étape consiste à obtenir ce jeton en envoyant une demande AJAX au rest/session/tokenpoint de terminaison:

var getCsrfToken = function(callback) {
    $.get(Drupal.url('rest/session/token'))
        .done(function (data) {
            var csrfToken = data;
            callback(csrfToken);
        });
}

NB:

  • Le callbackparamètre est une fonction de rappel qui sera appelée lorsque le jeton CSRF sera récupéré
  • Nous utilisons la Drupal.urlfonction pour obtenir l'URL de base du site

Ce jeton doit être envoyé avec un en- X-CSRF-Tokentête.

2. Connexion

Considérez le code HTML suivant:

<form id="login" method="post" action="" accept-charset="UTF-8">
    <div class="input-field">
        <input id="edit-name" name="name" type="text" class="validate">
        <label for="edit-name">Username or email address</label>
    </div>
    <div class="input-field">
        <input id="edit-pass" name="pass" type="password" class="validate">
        <label for="edit-pass">Password</label>
    </div>
    <p><a href="{{ url('user.pass') }}">Forgot your password?</a></p>
    <button type="submit" class="btn btn-default btn-submit">Sign in</button>
</form>

... et le code jQuery correspondant:

$('form#login').on('submit', function(e) {
    e.preventDefault();

    var inputUsername = $('#edit-name').val();
    var inputPassword = $('#edit-pass').val();

    if (inputUsername != '' && inputPassword != '') {
        getCsrfToken(function(csrfToken) {
            $.ajax({
                url: Drupal.url('user/login?_format=json'),
                type: 'POST',
                dataType: 'json',
                data: JSON.stringify({name: inputUsername, pass: inputPassword}),
                headers: {
                    'X-CSRF-Token': csrfToken
                },
            }).done(function(response) {
                if (response.current_user) {
                    console.log('The user is logged!');
                }
            }).fail(function(jqXHR, textStatus) {
                ...
            });
        });
    }
});

Ce code a été testé avec succès avec Drupal 8.3.

J'espère que cela t'aidera!

Guicara
la source
1

Oui, bien sûr, j'ai fait un blog sur la façon de le tester avec postman , et aussi un autre sur la façon de configurer votre site drupal .

Dans ce projet, j'ai fait une connexion pour Drupal avec angular, en utilisant le module Simple OAuth pour le jeton.

ValRob
la source