从Jwt Token检索数据- Flutter和Symfony

hrysbysz  于 2023-08-06  发布在  Flutter
关注(0)|答案(1)|浏览(106)

我正在开发一个连接到Symfony API的Flutter应用程序。身份验证后,我需要从令牌中检索连接到应用程序的用户的数据。
问题:我可以检索用户的角色,它是User类的属性(字符串数组)。但是,我不能为其他属性这样做。我测试了令牌是否包含密钥,结果显示它不包含除“roles”之外的任何密钥。
我将分享端点symfony、我的用户类、Flutter的登录以及如何从token检索角色
端点Symfony:

class AuthController extends AbstractController
{
    private $doctrine;
    private $jwtManager;

    
    public function __construct(ManagerRegistry $doctrine, JWTTokenManagerInterface $jwtManager) 
    {
        $this->doctrine = $doctrine;
        $this->jwtManager = $jwtManager;

    }

    /**
     * @Route("/api/login_check", name="app_login_check", methods={"POST"})
     */
    public function loginCheck(Request $request, UserPasswordHasherInterface $passwordEncoder): JsonResponse
    {
        $data = json_decode($request->getContent(), true);

        $cin = $data['cin'] ?? '';
        $password = $data['password'] ?? '';

        $user = $this->doctrine->getRepository(Utilisateur::class)->findOneBy(['cin' => $cin]);

        if (!$user || !$passwordEncoder->isPasswordValid($user, $password)) {
            throw new BadCredentialsException('Invalid cin or password');
        }

        $token = $this->jwtManager->create($user);

        return new JsonResponse(['token' => $token]);
    }

}

字符串
类别用户:

<?php

namespace App\Entity;

use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use App\Repository\UtilisateurRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
use Symfony\Component\Validator\Constraints as Assert;

#[ORM\Entity(repositoryClass: UtilisateurRepository::class)]
#[UniqueEntity(fields: ['cin'], message: 'There is already an account with this cin')]
#[Vich\Uploadable]
#[ApiResource(
    operations: [
        new Get()
    ]
)]
class Utilisateur implements UserInterface, PasswordAuthenticatedUserInterface
{

    #[ORM\Id]
    #[ORM\Column(length: 180, unique: true)]
    private ?string $cin = null;

    #[ORM\Column]
    private array $roles = [];

    #[ORM\OneToMany(mappedBy: 'utilisateur', targetEntity: Commentaire::class, cascade: ["remove"])]
    private Collection $commentaires;

    #[ORM\Column(length: 255)]
    private ?string $password = null;

    #[ORM\Column(length: 255, nullable: true)]
    private ?string $email = null;

    #[ORM\Column(length: 255, nullable: true)]
    private ?string $nom = null;

    #[ORM\Column(length: 255, nullable: true)]
    private ?string $prenom = null;

    #[ORM\Column(length: 10, nullable: true)]
    private ?string $genre = null;

    #[ORM\Column(length: 50, nullable: true)]
    private ?string $telephone = null;

    #[ORM\ManyToOne]
    private ?Profil $profil = null;

    #[ORM\ManyToOne(inversedBy: 'utilisateurs')]
    private ?Departement $departement = null;

    #[ORM\ManyToOne(inversedBy: 'utilisateurs')]
    private ?Pole $pole = null;

    #[ORM\ManyToOne(inversedBy: 'utilisateurs')]
    private ?Domaine $domaine = null;

    #[ORM\OneToMany(mappedBy: 'utilisateur', targetEntity: Document::class)]
    private Collection $documents;

    #[ORM\Column(type: 'boolean')]
    private $isVerified = false;

    #[ORM\OneToMany(mappedBy: 'utilisateur', targetEntity: UtilisateursTaches::class, cascade: ["remove"])]
    private Collection $utilisateursTaches;

    #[ORM\Column(length: 255, nullable: true)]
    #[Assert\NotBlank]
    private ?string $imageName = '';

    #[Vich\UploadableField(mapping: "utilisateur", fileNameProperty: "imageName")]
    private ?File $imageFile = null;


    public function __construct()
    {
        $this->commentaires = new ArrayCollection();
        $this->documents = new ArrayCollection();
        $this->utilisateursTaches = new ArrayCollection();
    }

    public function getCin(): ?string
    {
        return $this->cin;
    }

    public function setCin(string $cin): self
    {
        $this->cin = $cin;

        return $this;
    }

    /**
     * A visual identifier that represents this user.
     *
     * @see UserInterface
     */
    public function getUserIdentifier(): string
    {
        return (string) $this->cin;
    }

    /**
     * @see UserInterface
     */
    public function getRoles(): array
    {
        $roles = $this->roles;
        // guarantee every user at least has ROLE_USER
        $roles[] = 'ROLE_USER';

        return array_unique($roles);
    }

    public function setRoles(array $roles): self
    {
        $this->roles = $roles;

        return $this;
    }

    /**
     * @see UserInterface
     */
    public function eraseCredentials()
    {
        // If you store any temporary, sensitive data on the user, clear it here
        // $this->plainPassword = null;
    }

    /**
     * @return Collection<int, Commentaire>
     */
    public function getCommentaires(): Collection
    {
        return $this->commentaires;
    }

    public function addCommentaire(Commentaire $commentaire): self
    {
        if (!$this->commentaires->contains($commentaire)) {
            $this->commentaires->add($commentaire);
            $commentaire->setUtilisateur($this);
        }

        return $this;
    }

    public function removeCommentaire(Commentaire $commentaire): self
    {
        if ($this->commentaires->removeElement($commentaire)) {
            // set the owning side to null (unless already changed)
            if ($commentaire->getUtilisateur() === $this) {
                $commentaire->setUtilisateur(null);
            }
        }

        return $this;
    }

    public function getPassword(): ?string
    {
        return $this->password;
    }

    public function setPassword(string $password): self
    {
        $this->password = $password;

        return $this;
    }

    public function getEmail(): ?string
    {
        return $this->email;
    }

    public function setEmail(?string $email): self
    {
        $this->email = $email;

        return $this;
    }

    public function getNom(): ?string
    {
        return $this->nom;
    }

    public function setNom(?string $nom): self
    {
        $this->nom = $nom;

        return $this;
    }

    public function getPrenom(): ?string
    {
        return $this->prenom;
    }

    public function setPrenom(?string $prenom): self
    {
        $this->prenom = $prenom;

        return $this;
    }

    public function getGenre(): ?string
    {
        return $this->genre;
    }

    public function setGenre(?string $genre): self
    {
        $this->genre = $genre;

        return $this;
    }

    public function getTelephone(): ?string
    {
        return $this->telephone;
    }

    public function setTelephone(?string $telephone): self
    {
        $this->telephone = $telephone;

        return $this;
    }

    public function getProfil(): ?Profil
    {
        return $this->profil;
    }

    public function getProfilTitre(): ?string{
        if ($this->profil){
            return $this->profil->getTitreProfil();
        }
        return "";
    }

    public function setProfil(?Profil $profil): self
    {
        $this->profil = $profil;

        return $this;
    }

    public function getDepartement(): ?Departement
    {
        return $this->departement;
    }

    public function setDepartement(?Departement $departement): self
    {
        $this->departement = $departement;

        return $this;
    }

    public function getPole(): ?Pole
    {
        return $this->pole;
    }

    public function setPole(?Pole $pole): self
    {
        $this->pole = $pole;

        return $this;
    }

    public function getDomaine(): ?Domaine
    {
        return $this->domaine;
    }

    public function setDomaine(?Domaine $domaine): self
    {
        $this->domaine = $domaine;

        return $this;
    }

    /**
     * @return Collection<int, Document>
     */
    public function getDocuments(): Collection
    {
        return $this->documents;
    }

    public function addDocument(Document $document): self
    {
        if (!$this->documents->contains($document)) {
            $this->documents->add($document);
            $document->setUtilisateur($this);
        }

        return $this;
    }

    public function removeDocument(Document $document): self
    {
        if ($this->documents->removeElement($document)) {
            // set the owning side to null (unless already changed)
            if ($document->getUtilisateur() === $this) {
                $document->setUtilisateur(null);
            }
        }

        return $this;
    }

    public function isVerified(): bool
    {
        return $this->isVerified;
    }

    public function setIsVerified(bool $isVerified): self
    {
        $this->isVerified = $isVerified;

        return $this;
    }

    /**
     * @return Collection<int, UtilisateursTaches>
     */
    public function getUtilisateursTaches(): Collection
    {
        return $this->utilisateursTaches;
    }

    public function addUtilisateursTach(UtilisateursTaches $utilisateursTach): self
    {
        if (!$this->utilisateursTaches->contains($utilisateursTach)) {
            $this->utilisateursTaches->add($utilisateursTach);
            $utilisateursTach->setUtilisateur($this);
        }

        return $this;
    }

    public function removeUtilisateursTach(UtilisateursTaches $utilisateursTach): self
    {
        if ($this->utilisateursTaches->removeElement($utilisateursTach)) {
            // set the owning side to null (unless already changed)
            if ($utilisateursTach->getUtilisateur() === $this) {
                $utilisateursTach->setUtilisateur(null);
            }
        }

        return $this;
    }

    public function setImageName(?string $imageName): self
    {
        $this->imageName = $imageName;
        return $this;

    }

    public function setImageFile(?File $imageFile): self
    {
        $this->imageFile = $imageFile;
        return $this;

    }

    public function getImageName(): ?string
    {
        return $this->imageName;
    }

    public function getImageFile(): ?File
    {
        return $this->imageFile;
    }
}


登录Flutter

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';


class LoginPage extends StatefulWidget {
  @override
  _LoginPageState createState() => _LoginPageState();

}

class _LoginPageState extends State<LoginPage> {
  final TextEditingController _cinController = TextEditingController();
  final TextEditingController _passwordController = TextEditingController();
  String _message = '';

  Future<void> _login() async {
    String cin = _cinController.text;
    String password = _passwordController.text;

    final response = await http.post(
      Uri.parse('http://192.168.17.169:8000/api/login_check'), // Utilisez le bon endpoint pour la connexion
      headers: {'Content-Type': 'application/json'}, // Ajoutez l'en-tête de contenu JSON
      body: jsonEncode({'cin': cin, 'password': password}), // Encodez les données en JSON
    );

    if (response.statusCode == 200) {
      final responseData = jsonDecode(response.body);
      String token = responseData['token'];

      // Stockez le token dans les SharedPreferences
      SharedPreferences prefs = await SharedPreferences.getInstance();
      prefs.setString('token', token);

      Navigator.pushReplacementNamed(
        context,
        '/welcome',
      );
    } else {
      setState(() {
        _message = 'Invalid cin or password';
      });
    }
  }


  @override
  Widget build(BuildContext context) {
    //code.................
  }
}


从令牌检索角色:

import 'package:jwt_decoder/jwt_decoder.dart'; // Importez les dépendances nécessaires

List<String> getUserRolesFromToken(String jwtToken) {
  Map<String, dynamic> decodedToken = JwtDecoder.decode(jwtToken);
  dynamic roles = decodedToken['roles']; // Replace 'user_roles' with the actual key for the roles in your JWT token payload

  if (roles is List<dynamic>) {
    return roles.map((role) => role.toString()).toList();
  } else {
    return [];
  }
}

____

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'side_menu.dart';
import 'package:dembe/helpers/accessUser.dart';

class profil extends StatelessWidget {
  Future<String?> getToken() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    return prefs.getString('token');
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      drawer: SideMenu(), // Include the SideMenu widget here
      body: Center(
        child: FutureBuilder<String?>(
          future: getToken(),
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
              return CircularProgressIndicator(); // Afficher un indicateur de chargement en attendant que le token soit récupéré
            }
            else if (snapshot.hasError) {
              return Text('Error: ${snapshot.error}');
            } else if (snapshot.hasData && snapshot.data != null && snapshot.data!.isNotEmpty) {
              String token = snapshot.data!;
              List<String> userRoles = getUserRolesFromToken(token);
              String rolesString = userRoles.join(', '); // Convert the list to a comma-separated string
              
                return Text('Token: $token\nUser Role: $rolesString');
            }
            else {
              // Gérer le cas où le token est null ou vide
              return Text('Token not available');
            }
          },
        ),
      ),
    );
  }
  
}

a1o7rhls

a1o7rhls1#

你正在使用this bundle来生成jwt。但是,这个库只使用rolesusername(默认)来生成jwt有效负载。
如果您想添加自定义字段,请参考this article
prefs.setString是Future,所以必须使用setString使用await

await prefs.setString('token', token);

字符串

相关问题