主頁 > .NET開發 > 從SSO遠程主機驗證本地客戶端

從SSO遠程主機驗證本地客戶端

2022-11-17 13:34:35 .NET開發

我可能在這里弄錯了我的一些術語,但是經過幾天的反復試驗、谷歌搜索、symfony 檔案、在這里搜索和閱讀各種教程,我的頭可能有點炸了。

我在用什么:

  • PHP 8.1.0
  • 交響樂 (6)
  • 用于 EveOnline 的 Evelabs OAuth2 提供程式
  • MySQL 5.7
  • 教義

在其他作曲家包中

我想要做的是重定向想要通過 SSO (EveOnline) 登錄到我的網站的用戶,在回傳到我的網站后,存盤相關資料并驗證用戶以訪問我網站上的會員專區。

將來我將代表用戶發出 ESI (EveSwaggerInterface) 請求。

目前我有 SSO 使用 OAuth2,我正在構建 URL,重定向到 Eve,用戶登錄并回傳給我,然后我捕獲回應,填充/更新資料庫或捕獲錯誤,最后重定向成員區域,都在我的控制器中。


use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Evelabs\OAuth2\Client\Provider\EveOnline;
use Doctrine\Persistence\ManagerRegistry;
use App\Entity\User;

class SecurityController extends AbstractController
{
    #[Route('/login', name: 'page_login')]
    public function login_page()
    {
        return $this->render('login.html.twig');
    }

    #[Route('/redirect', name: 'app_login')]
    public function login(ManagerRegistry $doctrine)
    {
        session_start();

        $provider = new EveOnline([
            'clientId'          => $this->getParameter('eve.client_id'),
            'clientSecret'      => $this->getSecret,
            'redirectUri'       => $this->getParameter('eve.redirect_uri'),
        ]);
        if (!isset($_GET['code'])) {

            $options = [
                'scope' => ['publicData'] // array or string
            ];

            // If we don't have an authorization code then get one
            $authUrl = $provider->getAuthorizationUrl($options);
            $_SESSION['oauth2state'] = $provider->getState();
            unset($_SESSION['token']);
            header('Location: '.$authUrl);
            exit;

        // Check given state against previously stored one to mitigate CSRF attack
        } elseif (empty($_GET['state']) || ($_GET['state'] !== $_SESSION['oauth2state'])) {

            unset($_SESSION['oauth2state']);
            exit('Invalid state');

        } else{ // In this example we use php native $_SESSION as data store
            if(!isset($_SESSION['token']))
            {
                $_SESSION['token'] = $provider->getAccessToken('authorization_code', [
                    'code' => $_GET['code']
                ]);

            }elseif($_SESSION['token']->hasExpired()) {
                // This is how you refresh your access token once you have it
                $new_token = $provider->getAccessToken('refresh_token', [
                    'refresh_token' => $_SESSION['token']->getRefreshToken()
                ]);
                // Purge old access token and store new access token to your data store.
                $_SESSION['token'] = $new_token;
            }try{
                // Try to get an access token using the authorization code grant.
                $accessToken = $provider->getResourceOwner($_SESSION['token']);
                //Store eve user data
                $userdata = $accessToken->toArray();
                //Init Entity Manager
                $entityManager = $doctrine->getManager();
                //Get Repo
                $userobject = $doctrine->getRepository(User::class)->findBy(['userID' => $userdata['CharacterID']]);

                //If user exist, update database
                if ($accessToken && $userobject != null){
                    $id = $userobject[0]->getId();
                    $userobject[0]->setId($id);
                    $userobject[0]->setUserName($userdata['CharacterName']);
                    $userobject[0]->setUserID($userdata['CharacterID']);
                    $userobject[0]->setToken($_SESSION['token']->getToken());
                    $userobject[0]->setTokenRefresh($_SESSION['token']->getRefreshToken());
                    $userobject[0]->setExpiry($_SESSION['token']->getExpires());

                    $entityManager->flush();
                    //If user exists update tokens
                }elseif($accessToken != null){
                    $userobject = new User();
                    $userobject->setUserName($userdata['CharacterName']);
                    $userobject->setUserID($userdata['CharacterID']);
                    $userobject->setRoles(['ROLE_USER']);
                    $userobject->setToken($_SESSION['token']->getToken());
                    $userobject->setTokenRefresh($_SESSION['token']->getRefreshToken());
                    $userobject->setExpiry($_SESSION['token']->getExpires());

                    $entityManager->persist($userobject);
                    $entityManager->flush();
                }else{
                    print_r('You messed it all, go slap undo');
                    //TODO: Update this error with a real error
                }

            }catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) {

                // Failed to get the access token or user details.
                exit($e->getMessage());
            }
        }
        return $this->redirectToRoute('page_success');
    }


    #[Route('/success', name: 'page_success')]
    public function success()
    {
        return $this->render('callback.html.twig');
    }

}

我的問題是,我無法確定在何處或如何測驗用戶是否已登錄或設定標志以在本地驗證用戶。

我推測如果從 SSO 成功回傳并帶有有效負載,則用戶已通過遠程主機的身份驗證,當我設法設定經過身份驗證的標志時,我可以通過測驗應該重繪 的令牌來移動以使我的身份驗證程序更安全確認它不是虛假的有效載荷 && || 餅干

我的探查器顯示用戶未通過身份驗證,并且即使呼叫 session_start() 也根本沒有活動會話;雖然我可以轉儲($_SESSION['token']); 成功

任何幫助克服這個障礙的幫助將不勝感激

配置\安全.yaml

    enable_authenticator_manager: true
    # https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
    password_hashers:
        Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
    # https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
    providers:
        # used to reload user from session & other features (e.g. switch_user)
        app_user_provider:
            entity:
                class: App\Entity\User
                property: userID
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            lazy: true
            provider: app_user_provider

            # activate different ways to authenticate
            # https://symfony.com/doc/current/security.html#the-firewall

            # https://symfony.com/doc/current/security/impersonating_user.html
            # switch_user: true

    # Easy way to control access for large sections of your site
    # Note: Only the *first* access control that matches will be used
    access_control:
        # - { path: ^/admin, roles: ROLE_ADMIN }
        # - { path: ^/profile, roles: ROLE_USER }
#        - {path: ^/success, roles: ROLE_USER }

when@test:
    security:
        password_hashers:
            # By default, password hashers are resource intensive and take time. This is
            # important to generate secure password hashes. In tests however, secure hashes
            # are not important, waste resources and increase test times. The following
            # reduces the work factor to the lowest possible values.
            Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface:
                algorithm: auto
                cost: 4 # Lowest possible value for bcrypt
                time_cost: 3 # Lowest possible value for argon
                memory_cost: 10 # Lowest possible value for argon

物體\用戶 - 以防萬一


namespace App\Entity;

use App\Repository\UserRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;

#[ORM\Entity(repositoryClass: UserRepository::class)]
class User implements UserInterface
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

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

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

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

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

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

    #[ORM\Column(nullable: true)]
    private ?int $expiry = null;

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

    public function getId(): ?int
    {
        return $this->id;
    }

    public function setId(?int $id): self
    {
        $this->id = $id;

        return $this;
    }

    public function getUserID(): ?string
    {
        return $this->userID;
    }

    public function setUserID(string $userID): self
    {
        $this->userID = $userID;

        return $this;
    }

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

    /**
     * @deprecated since Symfony 5.3, use getUserIdentifier instead
     */
    public function getUsername(): string
    {
        return (string) $this->userID;
    }

    /**
     * @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;
    }

    /**
     * This method can be removed in Symfony 6.0 - is not needed for apps that do not check user passwords.
     *
     * @see PasswordAuthenticatedUserInterface
     */
    public function getPassword(): ?string
    {
        return null;
    }

    /**
     * This method can be removed in Symfony 6.0 - is not needed for apps that do not check user passwords.
     *
     * @see UserInterface
     */
    public function getSalt(): ?string
    {
        return null;
    }

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

    public function setUserName(string $userName): self
    {
        $this->userName = $userName;

        return $this;
    }

    public function getToken(): ?string
    {
        return $this->token;
    }

    public function setToken(?string $token): self
    {
        $this->token = $token;

        return $this;
    }

    public function getTokenRefresh(): ?string
    {
        return $this->tokenRefresh;
    }

    public function setTokenRefresh(?string $tokenRefresh): self
    {
        $this->tokenRefresh = $tokenRefresh;

        return $this;
    }

    public function getExpiry(): ?int
    {
        return $this->expiry;
    }

    public function setExpiry(?int $expiry): self
    {
        $this->expiry = $expiry;

        return $this;
    }

    public function getScopes(): ?string
    {
        return $this->scopes;
    }

    public function setScopes(?string $scopes): self
    {
        $this->scopes = $scopes;

        return $this;
    }
}

我在 v2 中有過一些使用 symfony 防火墻的經驗,但我使用了我的站點處理的登錄表單,但現在我使用的是 6.1,一切都不同了,并且使用了完全不同型別的提供商,我不能打電話默認身份驗證器,因為我沒有使用電子郵件密碼表單。

我必須構建一個自定義身份驗證器來處理它嗎?如果是這樣的話。我的代碼并不聰明,因此不勝感激外行人的解釋。

uj5u.com熱心網友回復:

當令牌過期時,我有一個啟示。

它似乎,

Oauth2 提供程式會在幕后或幕后檢查令牌過期時間,并在令牌過期且未重繪 時默認傳遞 HTTP 狀態 (500)。

symfony 6 防火墻被完全繞過并在其他地方的代碼中處理。

我使用的任何頁面都會session_start()成為“安全”頁面。如果會話資料已過期,Oauth 提供程式將拋出未經授權的例外。

這滿足了我的身份驗證問題,因為只要我需要將頁面視為成員,我只需要啟動一個會話,如果會話無效,則重定向用戶登錄

如果我錯了,請糾正我。

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/535537.html

標籤:PHP验证oauth-2.0单点登录symfony6

上一篇:如何僅為特定用戶添加費用?

下一篇:將服務注入Guard-Nestjs

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more