我正在开发一个连接到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');
}
},
),
),
);
}
}
型
1条答案
按热度按时间a1o7rhls1#
你正在使用this bundle来生成jwt。但是,这个库只使用
roles
和username
(默认)来生成jwt有效负载。如果您想添加自定义字段,请参考this article
而
prefs.setString
是Future,所以必须使用setString
使用await
字符串