স্বয়ংক্রিয়ভাবে পোস্ট-নিবন্ধকরণ ব্যবহারকারীর প্রমাণীকরণ


114

আমরা সিমফনি ২ তে গ্রাউন্ড আপ থেকে একটি ব্যবসায়িক অ্যাপ তৈরি করছি এবং আমি ব্যবহারকারী নিবন্ধকরণ প্রবাহের সাথে কিছুটা ছিনতাই করেছি: ব্যবহারকারী কোনও অ্যাকাউন্ট তৈরি করার পরে সেগুলি স্বয়ংক্রিয়ভাবে সেই শংসাপত্রগুলির সাথে লগইন করা উচিত অবিলম্বে আবার তাদের শংসাপত্র সরবরাহ করতে বাধ্য করা হচ্ছে।

কারও সাথে এটার কোনও অভিজ্ঞতা আছে, বা আমাকে সঠিক দিকে নির্দেশ করতে সক্ষম হয়েছে?

উত্তর:


146

সিমফনি 4.0

এই প্রক্রিয়াটি সিমফনি 3 থেকে 4 এ পরিবর্তিত হয়নি তবে এখানে নতুন প্রস্তাবিত অ্যাবস্ট্রাক্ট্রন্ট্রোলার ব্যবহার করে একটি উদাহরণ দেওয়া হয়েছে। উভয়ই পরিষেবাগুলি security.token_storageএবং sessionপরিষেবাগুলি প্যারেন্ট getSubscribedServicesপদ্ধতিতে নিবন্ধভুক্ত রয়েছে যাতে আপনার নিয়ামকগুলিতে সেগুলি যুক্ত করতে হয় না।

use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use YourNameSpace\UserBundle\Entity\User;

class LoginController extends AbstractController{

    public function registerAction()
    {    
        $user = //Handle getting or creating the user entity likely with a posted form
        $token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
        $this->container->get('security.token_storage')->setToken($token);
        $this->container->get('session')->set('_security_main', serialize($token));
        // The user is now logged in, you can redirect or do whatever.
    }

}

সিমফনি 2.6.x - সিমফনি 3.0.x

সিমফনি হিসাবে ২.6 security.contextএর পক্ষে অবমূল্যায়ন করা হয়েছে security.token_storage। নিয়ামক এখন সহজভাবে হতে পারে:

use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use YourNameSpace\UserBundle\Entity\User;

class LoginController extends Controller{

    public function registerAction()
    {    
        $user = //Handle getting or creating the user entity likely with a posted form
        $token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
        $this->get('security.token_storage')->setToken($token);
        $this->get('session')->set('_security_main', serialize($token));
    }

}

এটি অবহেলিত অবস্থায় আপনি এখনও ব্যবহার করতে পারবেন security.contextকারণ এটি পশ্চাদপটে সামঞ্জস্যপূর্ণ হয়েছে। সিমফনি 3 এর জন্য এটি আপডেট করার জন্য প্রস্তুত থাকুন

সুরক্ষার জন্য আপনি এখানে ২. changes টি পরিবর্তন সম্পর্কে আরও পড়তে পারেন: https://github.com/symfony/symfony/blob/2.6/UPGRADE-2.6.md

সিমফনি ২.৩.x

সিম্ফনি ২.৩ এ এটি পূরণ করতে আপনি আর সুরক্ষা প্রসঙ্গে টোকেনটি আর সেট করতে পারবেন না। আপনার সেশন টোকেন সংরক্ষণ করতে হবে।

ফায়ারওয়াল সহ সুরক্ষা ফাইলটি ধরে নেওয়া:

// app/config/security.yml
security:
    firewalls:
        main:
            //firewall settings here

এবং একই রকম একটি নিয়ামক পদক্ষেপ:

use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use YourNameSpace\UserBundle\Entity\User;

class LoginController extends Controller{

    public function registerAction()
    {    
        $user = //Handle getting or creating the user entity likely with a posted form
        $token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
        $this->get('security.context')->setToken($token);
        $this->get('session')->set('_security_main',serialize($token));
        //Now you can redirect where ever you need and the user will be logged in
    }

}

টোকেন তৈরির জন্য আপনি একটি তৈরি করতে চান UsernamePasswordToken, এটি 4 টি পরামিতি গ্রহণ করে: ব্যবহারকারী সত্তা, ব্যবহারকারীর শংসাপত্র, ফায়ারওয়াল নাম, ব্যবহারকারীর ভূমিকা। টোকেনটি বৈধ হওয়ার জন্য আপনাকে ব্যবহারকারীর শংসাপত্র সরবরাহ করতে হবে না।

আমি 100% নিশ্চিত নই যে security.contextআপনি যদি এখনই পুনঃনির্দেশ করতে চলেছেন তবে টোকেনটি সেট করা প্রয়োজনীয়। তবে এটা মনে হচ্ছে না যে আমি এটিকে ফেলে রেখেছি।

তারপরে গুরুত্বপূর্ণ অংশটি সেশন ভেরিয়েবল নির্ধারণ করুন। ভেরিয়েবলের নামকরণ কনভেনশনটি _security_আপনার ফায়ারওয়ালের নাম অনুসারে এই ক্ষেত্রে mainতৈরি হয়_security_main


1
আমি কোডটি প্রয়োগ করেছি, ব্যবহারকারী সাফল্যের সাথে লগইন করেছেন তবে $ this-> getUser () অবজেক্টটি NULL প্রদান করে। কোন ধারণা?
সতীশ

2
পাগল জিনিস ছাড়া ঘটছিল $this->get('session')->set('_security_main', serialize($token));। আপনাকে ধন্যবাদ, @ চেসার!
দিমিত্রি

1
Symfony 2.6 আপনি নামের এক ফায়ারওয়াল জন্য টোকেন সেট যদি mainএবং আপনি নামে আরেকটি ফায়ারওয়াল সঙ্গে প্রমাণীকৃত admin(যেমন আপনি যদি ব্যবহারকারীর ছদ্মবেশ ধারণ করা হয়), একটি অদ্ভুত জিনিস ঘটবে: _security_adminপায় UsernamePasswordTokenব্যবহারকারী আপনার দেওয়া সঙ্গে, অর্থাত আপনার কাছ থেকে "বিচ্ছিন্ন" পেতে তোমার adminফায়ারওয়াল "অ্যাডমিন" ফায়ারওয়ালের টোকেন কীভাবে বজায় রাখা যায় তার কোনও ধারণা?
গ্রিমো

1
সত্য কথা বলতে গেলে আপনার একই সাথে ২ টি ফায়ারওয়ালের প্রমাণীকরণ হতে পারে তা নিশ্চিত নন, এটির দিকে খারাপ দৃষ্টিপাত করুন তবে মাঝামাঝি সময়ে আপনাকে একটি পৃথক প্রশ্ন জিজ্ঞাসা করা উচিত
চেজ

3
@ চেসার এটি কাজ করতে সক্ষম হয়েছেন। আপনার উত্তরটি পুরোপুরি সঠিক (এবং এটি আপডেট হয়েছে), কেবলমাত্র যখন আপনি একই লক্ষ্য ফায়ারওয়ালেরsetToken(..) অধীনে কল করেন বা এখনও প্রমাণীকরণ না করে কেবল তখনই এটি কাজ করে ।
গ্রেভো

65

শেষ পর্যন্ত এই এক খুঁজে।

ব্যবহারকারীর নিবন্ধকরণের পরে, আপনার সরবরাহকারীর কনফিগারেশনে আপনার ব্যবহারকারীর সত্তা হিসাবে যা কিছু সেট করেছেন তাতে আপনার কোনও অবজেক্টের অ্যাক্সেস থাকা উচিত। সমাধানটি হ'ল সেই ব্যবহারকারীর সত্তার সাথে একটি নতুন টোকেন তৈরি করা এবং এটি সুরক্ষা প্রসঙ্গে। আমার সেটআপের উপর ভিত্তি করে এখানে একটি উদাহরণ রয়েছে:

RegistrationController.php:

$token = new UsernamePasswordToken($userEntity, null, 'main', array('ROLE_USER'));
$this->get('security.context')->setToken($token);

mainআপনার অ্যাপ্লিকেশনটির জন্য ফায়ারওয়ালের নাম কোথায় (ধন্যবাদ, @ জো)। সত্যিই এটুকুই আছে; সিস্টেমটি এখন আপনার ব্যবহারকারীকে সম্পূর্ণরূপে লগ ইন করা ব্যবহারকারী হিসাবে সবেমাত্র তারা তৈরি করেছে consid

সম্পাদনা: মাইকেলের মন্তব্য অনুসারে, নতুন ব্যবহারকারীর বুদ্ধিমান ডিফল্ট ভূমিকা অন্তর্ভুক্ত করতে আমি নিয়ামক কোডের নমুনা আপডেট করেছি (যদিও স্পষ্টতই এটি আপনার অ্যাপ্লিকেশনটির নির্দিষ্ট প্রয়োজন অনুসারে সামঞ্জস্য করা যেতে পারে)।


2
এটি সিমফনি ২ এর মুক্তির সংস্করণটির সাথে একেবারেই ঠিক নয় You আপনার ব্যবহারকারীর ভূমিকাগুলি ব্যবহারকারীর নামপ্যাসওয়ার্ড টোকেন কনস্ট্রাক্টরের কাছে চতুর্থ যুক্তি হিসাবে পাস করতে হবে, অথবা এটি অরক্ষিত হিসাবে চিহ্নিত হবে এবং ব্যবহারকারীর কোনও ভূমিকা থাকবে না।
মাইকেল 14

"আমাকে স্মরণ করুন" পতাকাটি কী? ব্যবহারকারীরা কীভাবে হাত দিয়ে লগইন করবেন তবে তাদের চিরতরে লগ ইন করা উচিত। কোডের এই অংশটি এই সমস্যাটিকে সমাধান করে না।
matepo

@ মেকটপো যা আমার আসল প্রয়োজনীয়তার আওতায় ছিল না, তবে দুর্দান্ত ফলোআপ উত্তর বলে মনে হচ্ছে। আমাদের আপনার সাথে আসা কি জানি।
সমস্যাযুক্ত

আমার একটা সমস্যা আছে আমি এইভাবে লগ ইন করতে পারি তবে আমি অ্যাপ্লিকেশন ব্যবহারকারীর ভেরিয়েবলটি খালি is আপনি এই লগইন প্রক্রিয়া এই পরিবর্তনশীল পপুলেট উপায় জানেন কি? - আমি ব্যবহারকারী (স্ট্রিং) এবং পাসওয়ার্ড (স্ট্রিং) প্রেরণ হিসাবে রেফারেন্স: api.symfony.com/2.0/Symfony/Comp घटक
Security

1
মার্ক নীচের মত বলেছে, আপনার ব্যবহারকারীর নাম use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
পাসওয়ার্ড টোকেন

6

আপনার যদি ইউজারআইন্টারফেস অবজেক্ট থাকে (এবং এটি বেশিরভাগ ক্ষেত্রে হওয়া উচিত) আপনি গেটরোলস ফাংশনটি এটি ব্যবহার করতে পারেন যা এটি শেষ যুক্তির জন্য প্রয়োগ করে। সুতরাং আপনি যদি কোনও ফাংশন লগ ইউজার তৈরি করেন তবে এটির মতো দেখতে হবে:

public function logUser(UserInterface $user) {
    $token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
    $this->container->get('security.context')->setToken($token);
}

6

আমি সিমফনি ২.২ ব্যবহার করছি এবং আমার অভিজ্ঞতা সমস্যাযুক্তের চেয়ে কিছুটা আলাদা ছিল , সুতরাং এটি এই প্রশ্নটি এবং আমার নিজের কিছু থেকে সমস্ত তথ্যের সম্মিলিত সংস্করণ।

আমি মনে করি জো এর মান সম্পর্কে ভুল $providerKey, UsernamePasswordTokenনির্মাণকারীর তৃতীয় প্যারামিটার । এটি কোনও প্রমাণীকরণের (ব্যবহারকারী নয়) সরবরাহকারীর কী বলে মনে করা হচ্ছে। এটি বিভিন্ন সরবরাহকারীর জন্য তৈরি টোকেনের মধ্যে পার্থক্য করতে প্রমাণীকরণ সিস্টেম দ্বারা ব্যবহৃত হয়। যে কোনও সরবরাহকারীর কাছ থেকে নেমে আসা UserAuthenticationProviderকেবলমাত্র টোকেনগুলির প্রমাণীকরণ করবে যার সরবরাহকারী কী তার নিজের সাথে মেলে। উদাহরণস্বরূপ, UsernamePasswordFormAuthenticationListenerসেটগুলি তার সম্পর্কিতটির সাথে মেলে এটি তৈরি করা টোকেনের কীটি সেট করে DaoAuthenticationProvider। এটি একটি ফায়ারওয়ালের একাধিক ব্যবহারকারীর নাম + পাসওয়ার্ড সরবরাহকারী একে অপরকে পদক্ষেপ না করেই থাকতে দেয়। অতএব আমাদের এমন কী নির্বাচন করতে হবে যা অন্য কোনও সরবরাহকারীর সাথে দ্বন্দ্ব না করে। আমি ব্যবহার 'new_user'

আমার অ্যাপ্লিকেশনের অন্যান্য অংশে আমার কাছে কয়েকটি সিস্টেম রয়েছে যা প্রমাণীকরণ সাফল্যের ইভেন্টের উপর নির্ভর করে এবং কেবল প্রসঙ্গে টোকেন সেট করে এটি বরখাস্ত হয় না। আমাকে ধারকটি থেকে পেয়ে EventDispatcherঘটনাটি ম্যানুয়ালি ফায়ার করতে হয়েছিল। আমি ইন্টারেক্টিভ লগইন ইভেন্টের গুলি চালানোর বিরুদ্ধেও সিদ্ধান্ত নিয়েছিলাম কারণ আমরা স্পষ্টভাবে লগইন অনুরোধের প্রতিক্রিয়া হিসাবে নয়, ব্যবহারকারীকে স্পষ্টভাবে প্রমাণীকরণ করছি।

use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\AuthenticationEvents;
use Symfony\Component\Security\Core\Event\AuthenticationEvent;

$user = // get a Symfony user instance somehow
$token = new UsernamePasswordToken(
        $user, null, 'new_user', $user->getRoles() );
$this->get( 'security.context' )->setToken( $token );
$this->get( 'event_dispatcher' )->dispatch(
        AuthenticationEvents::AUTHENTICATION_SUCCESS,
        new AuthenticationEvent( $token ) );

নোট করুন যে $this->get( .. )স্নিপেটটি ব্যবহার করে একটি নিয়ামক পদ্ধতিতে। আপনি যদি অন্য কোথাও কোডটি ব্যবহার করেন তবে ContainerInterface::get( ... )আপনাকে সেগুলি পরিবেশের জন্য উপযুক্ত উপায়ে কল করতে হবে। এটির সাথে সাথে আমার ব্যবহারকারীর সত্ত্বাগুলি প্রয়োগ করে UserInterfaceতাই আমি তাদের সরাসরি টোকেনের সাহায্যে ব্যবহার করতে পারি। যদি আপনার না হয় তবে আপনাকে সেগুলিকে UserInterfaceদৃষ্টান্তে রূপান্তর করার জন্য কোনও উপায় খুঁজে বের করতে হবে ।

এই কোডটি কাজ করে, তবে আমি মনে করি এটি সিমফোনির প্রমাণীকরণ আর্কিটেকচারের সাথে কাজ করার চেয়ে এটি হ্যাক করছে। হাইজ্যাক না করে নিজের টোকেন শ্রেণীর দ্বারা কোনও নতুন প্রমাণীকরণ সরবরাহকারীকে সম্ভবত প্রয়োগ করা আরও সঠিক হবে UsernamePasswordToken। এছাড়াও, একটি উপযুক্ত সরবরাহকারী ব্যবহার করার অর্থ ইভেন্টগুলি আপনার জন্য পরিচালিত হয়েছিল।


4

কারও ক্ষেত্রে একই ফলো-অন প্রশ্ন রয়েছে যা আমাকে এখানে ফিরে আসতে বাধ্য করেছে:

কল করা হচ্ছে

$this->container->get('security.context')->setToken($token); 

security.contextব্যবহৃত রুটের জন্য কেবল বর্তমানকে প্রভাবিত করে ।

অর্থাৎ আপনি কেবল কোনও ফায়ারওয়ালের নিয়ন্ত্রণের মধ্যে থাকা কোনও ইউআরএল থেকে কোনও ব্যবহারকারীকে লগইন করতে পারেন।

(প্রয়োজনে রুটের ব্যতিক্রম যুক্ত করুন - IS_AUTHENTICATED_ANONYMOUSLY )


1
আপনি কি জানেন যে আপনি একটি সেশনের জন্য এটি কীভাবে করেন? বরং কেবল বর্তমান অনুরোধের জন্য?
জ্যাক এন

3

সিমফনি ৪.৪ এর সাহায্যে আপনি নিজের কন্ট্রোলার পদ্ধতিতে কেবল নিম্নলিখিতটি করতে পারেন (সিমফনি ডকুমেন্টেশন থেকে দেখুন: https://symfony.com/doc/current/security/guard_authentication.html#manman-authenticating-a-user ):

// src/Controller/RegistrationController.php
// ...

use App\Security\LoginFormAuthenticator;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;

class RegistrationController extends AbstractController
{
    public function register(LoginFormAuthenticator $authenticator, GuardAuthenticatorHandler $guardHandler, Request $request)
    {
        // ...

        // after validating the user and saving them to the database
        // authenticate the user and use onAuthenticationSuccess on the authenticator
        return $guardHandler->authenticateUserAndHandleSuccess(
            $user,          // the User object you just created
            $request,
            $authenticator, // authenticator whose onAuthenticationSuccess you want to use
            'main'          // the name of your firewall in security.yaml
        );
    }
}

একটি গুরুত্বপূর্ণ বিষয়, আপনার ফায়ারওয়াল সেট করা নেই তা নিশ্চিত করুন lazy। যদি তা হয়, টোকেনটি কখনই সেশনে সংরক্ষণ করা হবে না এবং আপনি কখনই লগ ইন করতে পারবেন না।

firewalls:
    main:
        anonymous: ~ # this and not 'lazy'

2

সমস্যা হিসাবে এখানে ইতিমধ্যে উল্লেখ করা হয়েছে, এই অধরা-সরবরাহকারী কে প্যারামিটারটি বাস্তবে নীচে উদাহরণের ক্ষেত্রে আপনার ফায়ারওয়াল নিয়মের নাম 'ফুবার' ছাড়া আর কিছুই নয়।

firewalls:
    foobar:
        pattern:    /foo/

আপনি কি আমাকে ব্যাখ্যা করতে পারেন আমি যদি blablablaইউজারনেম পাসওয়ার্ড টোকেনকে তৃতীয় প্যারামিটার হিসাবে উদাহরণস্বরূপ কোনও স্ট্রিংটি পাস করি তবে এটি খুব কার্যকর হবে কেন? এই পরামিতি মানে কি?
মিখাইল

1
এই প্যারামিটারটি আপনার টোকেনটিকে একটি নির্দিষ্ট ফায়ারওয়াল সরবরাহকারীর সাথে আবদ্ধ করে। বেশিরভাগ ক্ষেত্রে আপনার কেবলমাত্র সরবরাহকারী থাকবেন, তাই এটি নিয়ে মাথা ঘামান না।
গটলিয়েব নটসনাবেল

2

আমি এখানে সমস্ত উত্তর চেষ্টা করেছিলাম এবং কেউই কাজ করে না। নিয়ন্ত্রকের মাধ্যমে আমি আমার ব্যবহারকারীদের অনুমোদনের একমাত্র উপায় হ'ল একটি সাবক্রাইস্ট এবং তারপরে পুনঃনির্দেশ করা। এখানে আমার কোডটি রয়েছে, আমি সাইলেক্স ব্যবহার করছি তবে আপনি সহজেই এটি সিম্ফনি 2 এর সাথে মানিয়ে নিতে পারেন:

$subRequest = Request::create($app['url_generator']->generate('login_check'), 'POST', array('_username' => $email, '_password' => $password, $request->cookies->all(), array(), $request->server->all());

$response = $app->handle($subRequest, HttpKernelInterface::MASTER_REQUEST, false);

return $app->redirect($app['url_generator']->generate('curriculos.editar'));

1

সিমফনি সংস্করণ ২.৮.১১ এ (সম্ভবত পুরানো এবং আরও নতুন সংস্করণের জন্য কাজ করছে), আপনি যদি FOSUserBundle ব্যবহার করেন তবে এটি সহজভাবে করুন:

try {
    $this->container->get('fos_user.security.login_manager')->loginUser(
    $this->container->getParameter('fos_user.firewall_name'), $user, null);
} catch (AccountStatusException $ex) {
    // We simply do not authenticate users which do not pass the user
    // checker (not enabled, expired, etc.).
}

আমি অন্যান্য সমাধানে দেখেছি ইভেন্ট প্রেরণের দরকার নেই।

এফওএস \ ইউজারবান্ডেল \ কন্ট্রোলার \ রেজিস্ট্রেশনকন্ট্রোলার :: প্রমাণী ব্যবহারকারী

(কম্পোজার.জেসন ফসুউজারবান্ডেল সংস্করণ থেকে: "ফ্রেন্ডসফাইসফোনি / ইউজার-বান্ডেল": "~ 1.3")

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.