l3/cas-guard-bundle

适用于 Symfony3, Symfony4, Symfony5, Symfony6, Symfony7 的 PHPCas 包装器

安装数: 5,083

依赖项: 0

建议者: 0

安全性: 0

星标: 8

关注者: 1

分支: 4

开放性问题: 4

类型:symfony-bundle

1.1.16 2023-12-24 14:06 UTC

This package is auto-updated.

Last update: 2024-09-24 15:51:47 UTC


README

Symfony Cas Guard Bundle

此包是基于经典 jasig/phpCAS 库的依赖性包装器。

支持单点登出(BeSimpleSSoBundle 不支持)。

安装

使用以下命令安装包

composer require l3/cas-guard-bundle:~1.0

在 Symfony 的 Kernel 中声明 Bundle

对于 Symfony3,将 Bundle 添加到 app/AppKernel.php 中

<?php
// app/AppKernel.php

// ...
class AppKernel extends Kernel
{
    public function registerBundles()
    {
        $bundles = array(
            // ...

            new L3\Bundle\CasGuardBundle\L3CasGuardBundle(),
        );

        // ...
    }

    // ...
}

对于 Symfony4、Symfony5、Symfony6 和 Symfony7,将 Bundle 添加到 config/bundles.php 中(如果不存在行)

<?php

return [
    ...
    L3\Bundle\CasGuardBundle\L3CasGuardBundle::class => ['all' => true],
    ...
];

Bundle 配置

对于 Symfony3,将 l3_cas_guard 参数添加到您的配置文件(parameters.yml 和 parameters.yml.dist)中

l3_cas_guard:
    host: cas-test.univ-lille3.fr                       # Cas Server
    path: ~                                             # App path if not in root (eg. cas.test.com/cas)
    port: 443                                           # Server port
    ca: false                                           # SSL Certificate
    handleLogoutRequest: true                           # Single sign out activation (default: false)
    casLogoutTarget: https://ent-test.univ-lille3.fr    # Redirect path after logout
    force: true                                         # Allows cas check mode and not force, user : __NO_USER__ if not connected (If force false, Single sign out cant work).
    gateway: true					# Gateway mode (for use the mode gateway of the Cas Server) set to false if you use micro-services or apis rest.

对于 Symfony4、Symfony5 和 Symfony6,将变量添加到您的配置文件(.env 和 .env.dist)中

...
###> l3/cas-guard-bundle ###
CAS_HOST=cas-test.univ-lille3.fr     # Cas Server
CAS_PATH=~                           # App path if not in root (eg. cas.test.com/cas)
CAS_PORT=443                         # Server port
CAS_CA=false                         # SSL Certificate
CAS_HANDLE_LOGOUT_REQUEST=true       # Single sign out activation (default: false)
CAS_LOGIN_TARGET=https://server.univ-lille3.fr # Redirect path after login (when use anonymous mode)
CAS_LOGOUT_TARGET=https://ent-test.univ-lille3.fr    # Redirect path after logout
CAS_FORCE=true                       # Allows cas check mode and not force, user : __NO_USER__ if not connected (If force false, Single sign out cant work).
CAS_GATEWAY=true		     # Gateway mode (for use the mode gateway of the Cas Server) set to false if you use micro-services or apis rest.
###< l3/cas-guard-bundle ###
...

并在您的 config/services.yml 文件中添加参数(在 parameters 下)

...
parameters:
    cas_login_target: '%env(string:CAS_LOGIN_TARGET)%'
    cas_logout_target: '%env(string:CAS_LOGOUT_TARGET)%'
    cas_host: '%env(string:CAS_HOST)%'
    cas_port: '%env(int:CAS_PORT)%'
    cas_path: '%env(string:CAS_PATH)%'
    cas_gateway: '%env(bool:CAS_GATEWAY)%'

l3_cas_guard:
    host: '%env(string:CAS_HOST)%'
    path: '%env(string:CAS_PATH)%'
    port: '%env(int:CAS_PORT)%'
    ca: '%env(bool:CAS_CA)%'
    handleLogoutRequest: '%env(bool:CAS_HANDLE_LOGOUT_REQUEST)%'
    casLogoutTarget: '%env(string:CAS_LOGOUT_TARGET)%'
    force: '%env(bool:CAS_FORCE)%'
    gateway: '%env(bool:CAS_GATEWAY)%'
...

对于 Symfony7,将变量添加到您的配置文件(.env 和 .env.dist)中

...
###> l3/cas-guard-bundle ###
CAS_HOST=cas-test.univ-lille3.fr     # Cas Server
CAS_PATH=~                           # App path if not in root (eg. cas.test.com/cas)
CAS_PORT=443                         # Server port
CAS_CA=false                         # SSL Certificate
CAS_HANDLE_LOGOUT_REQUEST=true       # Single sign out activation (default: false)
CAS_SERVICE_BASE_URL=https://server.univ-lille3.fr # Service base URL how authorized to consume server cas
CAS_LOGIN_TARGET=https://server.univ-lille3.fr # Redirect path after login (when use anonymous mode)
CAS_LOGOUT_TARGET=https://ent-test.univ-lille3.fr    # Redirect path after logout
CAS_FORCE=true                       # Allows cas check mode and not force, user : __NO_USER__ if not connected (If force false, Single sign out cant work).
CAS_GATEWAY=true                     # Gateway mode (for use the mode gateway of the Cas Server) set to false if you use micro-services or apis rest.
###< l3/cas-guard-bundle ###
...

并在您的 config/services.yml 文件中添加参数(在 parameters 下)

...
parameters:
    cas_login_target: '%env(string:CAS_LOGIN_TARGET)%'
    cas_logout_target: '%env(string:CAS_LOGOUT_TARGET)%'
    cas_host: '%env(string:CAS_HOST)%'
    cas_port: '%env(int:CAS_PORT)%'
    cas_path: '%env(string:CAS_PATH)%'
    cas_gateway: '%env(bool:CAS_GATEWAY)%'

l3_cas_guard:
    host: '%env(string:CAS_HOST)%'
    path: '%env(string:CAS_PATH)%'
    port: '%env(int:CAS_PORT)%'
    ca: '%env(bool:CAS_CA)%'
    handleLogoutRequest: '%env(bool:CAS_HANDLE_LOGOUT_REQUEST)%'
    casServiceBaseUrl: '%env(string:CAS_SERVICE_BASE_URL)%'
    casLogoutTarget: '%env(string:CAS_LOGOUT_TARGET)%'
    force: '%env(bool:CAS_FORCE)%'
    gateway: '%env(bool:CAS_GATEWAY)%'
...

安全性配置

对于 Symfony3、Symfony4 或 Symfony5,在 app/config/security.yml 中的安全文件中配置防火墙

security:
    providers:
            # ...


    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt|error)|css|images|js)/
            security: false

        l3_firewall:
            pattern: ^/
            security: true
            guard:
                authenticators:
                    - cas.security.authentication.authenticator

对于 Symfony6 和 Symfony7

security:
    providers:
            # ...


    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt|error)|css|images|js)/
            security: false

        l3_firewall:
            pattern: ^/
            security: true
            custom_authenticators:
                - cas.security.authentication.authenticator

匿名配置

请注意,如果您想使用匿名模式,则 bundle cas 使用登录 NO_USER,使用以下安全设置

security:
    providers:
        chain_provider:
            chain:
                providers: [in_memory, your_userbundle]
        in_memory:
            memory:
                users:
                    __NO_USER__:
                        password:
                        roles: ROLE_ANON
        your_userbundle:
            id: your_userbundle

在 Symfony4 中,如果您使用 chain_provider,则应在 config/packages/security.yaml 中的所有条目(例如 l3_firewall 和 main)防火墙(在 security 激活的地方:security: true)上设置提供者名称,如下所示

# config/packages/security.yaml
security:
    providers:
        chain_provider:
            chain:
                providers: [in_memory, your_userbundle]
        in_memory:
            memory:
                users:
                    __NO_USER__:
                        password:
                        roles: ROLE_ANON
        your_userbundle:
            id: your_userbundle

    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false

        l3_firewall:
            pattern: ^/
            security: true
            provider: chain_provider
            guard:
                authenticators:
                    - cas.security.authentication.authenticator
            
        main:
            pattern: ^/
            security: true
            anonymous: true
            provider: chain_provider
            guard:
                authenticators:
                    - cas.security.authentication.authenticator

接下来在 app/config/parameters.yml(对于 Symfony3)和 config/services.yaml(对于 Symfony4)中将 force 设置为 false

l3_cas_guard:
    ...
    force: false                                         # Allows cas check mode and not force, user : __NO_USER__ if not connected (If force false, Single sign out cant work).

对于 Symfony3,在 app/config/security.yml 中将 default: anonymous

security:
    providers:
            # ...


    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt|error)|css|images|js)/
            security: false

        l3_firewall:
            pattern: ^/
            security: true
            guard:
                authenticators:
                    - cas.security.authentication.authenticator

        default:
            anonymous: ~
            guard:
                authenticators:
                    - cas.security.authentication.authenticator            

对于 Symfony4,在 config/packages/security.yaml 中将 main: anonymous

security:
    providers:
            # ...


    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false

        l3_firewall:
            pattern: ^/
            security: true
            guard:
                authenticators:
                    - cas.security.authentication.authenticator

        main:
            anonymous: ~
            pattern: ^/
            security: true
            guard:
                authenticators:
                    - cas.security.authentication.authenticator

对于 Symfony 5,将 anonymous: true 替换为 lazy: true,如下所示

        main:
            pattern: ^/
            security: true
            lazy: true
            provider: chain_provider
            guard:
                authenticators:
                    - cas.security.authentication.authenticator

对于 Symfony 6 和 Symfony7,将 anonymous: true 替换为 lazy: true,如下所示

        main:
            pattern: ^/
            security: true
            lazy: true
            provider: chain_provider
            custom_authenticators:
                - cas.security.authentication.authenticator

对于 Symfony3,在 app/config/parameters.yml.dist 和 app/config/parameters.yml 下的参数中添加 cas_host、cas_login_target、cas_path 和 cas_gateway

	...
        cas_login_target: https://your_web_path_application.com/
        cas_logout_target: https://your_web_path_application.com/
        cas_host: cas-test.univ-lille3.fr
        cas_path: ~
        cas_gateway: true
	...

对于 Symfony4、Symfony5、Symfony6 和 Symfony7,在 config/services.yaml 下的参数中添加 cas_host 和 cas_login_target

        ...
        cas_login_target: '%env(string:CAS_LOGIN_TARGET)%'
        cas_logout_target: '%env(string:CAS_LOGIN_TARGET)%'
        cas_host: '%env(string:CAS_HOST)%'
        cas_port: '%env(int:CAS_PORT)%'
        cas_path: '%env(string:CAS_PATH)%'
        cas_gateway: '%env(bool:CAS_GATEWAY)%'
        ...

对于 Symfony 3 和 Symfony 4,在您的应用程序的 DefaultController 中创建登录路由和强制路由

/**
 * @Route("/login", name="login")
 */
public function loginAction() {
        
	$url = 'https://'.$this->container->getParameter('cas_host') . $this->container->getParameter('cas_path') . '/login?service=';
        $target = $this->container->getParameter('cas_login_target');

        return $this->redirect($url . urlencode($target . '/force'));
}


/**
 * @Route("/force", name="force")
 */
public function forceAction() {

	if ($this->container->getParameter('cas_gateway')) {
        	if (!isset($_SESSION)) {
                	session_start();
        	}

        	session_destroy();
	}

        return $this->redirect($this->generateUrl('homepage'));
}

对于 Symfony 5,在您的应用程序的 DefaultController 中创建登录路由和强制路由

    /**
     * @Route("/login", name="login")
     */
    public function login(Request $request) {
           $url = 'https://'.$this->getParameter('cas_host') . $this->getParameter('cas_path') . '/login?service=';
           $target = $this->getParameter('cas_login_target');
           return $this->redirect($url . urlencode($target . '/force'));
    }
    
    /**
     * @Route("/force", name="force")
     */
    public function force(Request $request) {

            if ($this->getParameter('cas_gateway')) {
                if (!isset($_SESSION)) {
                        session_start();
                }

                session_destroy();
            }

            return $this->redirect($this->generateUrl('index'));
    }

对于 Symfony 6,创建此控制器 src/Controller/DefaultController.php

<?php

namespace App\Controller;

use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class DefaultController extends AbstractController
{
    /**
     * @Route("/login", name="login")
     */
    public function login(Request $request) {
           $target = urlencode($this->getParameter('cas_login_target').'/force');
           $url = 'https://'.$this->getParameter('cas_host') . ((($this->getParameter('cas_port')!=80) || ($this->getParameter('cas_port')!=443)) ? ":".$this->getParameter('cas_port') : "") . $this->getParameter('cas_path') . '/login?service=';
           return $this->redirect($url . $target);
    }
    
    /**
     * @Route("/logout", name="logout")
     */
    public function logout(Request $request) {
        if (($this->getParameter('cas_logout_target') !== null) && (!empty($this->getParameter('cas_logout_target')))) {
            \phpCAS::logoutWithRedirectService($this->getParameter('cas_logout_target'));
        } else {
            \phpCAS::logout();
        }
    }
    
    /**
     * @Route("/force", name="force")
     */
    public function force(Request $request) {

            if ($this->getParameter("cas_gateway")) {
                if (!isset($_SESSION)) {
                        session_start();
                }

                session_destroy();
            }

            return $this->redirect($this->generateUrl('index'));
    }
    
    
    /**
     * @Route("/", name="index")
     */
    public function index(Request $request) : Response
    {
        dump($this->container->get('security.token_storage'));
        dump($this->getUser());
        
        return $this->render('base.html.twig', []);
    }
}

对于 Symfony 7,创建此控制器 src/Controller/DefaultController.php

<?php

namespace App\Controller;

use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class DefaultController extends AbstractController
{
    #[Route('/login', name:'login', methods: ['GET'])]
    public function login(Request $request) {
           $target = urlencode($this->getParameter('cas_login_target').'/force');
           $url = 'https://'.$this->getParameter('cas_host') . ((($this->getParameter('cas_port')!=80) || ($this->getParameter('cas_port')!=443)) ? ":".$this->getParameter('cas_port') : "") . $this->getParameter('cas_path') . '/login?service=';

           return $this->redirect($url . $target);
    }
    
    #[Route('/logout', name:'logout', methods: ['GET'])]
    public function logout(Request $request) {
        if (($this->getParameter('cas_logout_target') !== null) && (!empty($this->getParameter('cas_logout_target')))) {
            \phpCAS::logoutWithRedirectService($this->getParameter('cas_logout_target'));
        } else {
            \phpCAS::logout();
        }
    }
    
    #[Route('/force', name:'force', methods: ['GET'])]
    public function force(Request $request) {

            if ($this->getParameter("cas_gateway")) {
                if (!isset($_SESSION)) {
                        session_start();
                }

                session_destroy();
            }

            return $this->redirect($this->generateUrl('index'));
    }
    
    
    #[Route('/', name:'index', methods: ['GET'])]
    public function index(Request $request) : Response
    {
        dump($this->container->get('security.token_storage'));
        dump($this->getUser());
        
        return $this->render('base.html.twig', []);
    }
}

最后,您可以使用路由 /login 来调用 cas 登录页面,并将其重定向到您的应用程序,然后您就登录了 :)

单点登出配置

为了使用单点登出,建议在 Symfony 中禁用 Symfony Sessions(这样您将使用 PHP 本地会话)。

# app/config/config.yml (Symfony3)
# config/packages/framework.yaml (for Symfony4 and Symfony5 and Symfony6)
framework:
    # ...
    session:
        handler_id:  ~
        save_path: ~

信息:该包与 PHPCas 进行检查,以检测一些 PHPCAS 未完全实现的断开连接请求(有关详细信息,请参阅 L3\Bundle\CasGuardBundle\Security\CasAuthenticator::checkHandleLogout())

用户提供者

对于LDAP用户,您可以使用LdapUserBundle(分支ou=people)或LdapUdlUserBundle(分支ou=accounts)。您还可以使用只返回uid的简单UidUserBundle。

您还可以使用FOSUserBundle...,例如://security.yml

    providers:
        chain_provider:
            chain:
                providers: [in_memory, fos_userbundle]
        in_memory:
            memory:
                users:
                    __NO_USER__:
                        password:
                        roles: ROLE_ANON
        fos_userbundle:
            id: fos_user.user_provider.username

注销路由

在Symfony 3中,如果您想使用/logout路由来调用注销,您可以在您的routing.yml中添加此内容

l3_logout:
    path:     /logout
    defaults: { _controller: L3CasBundle:Logout:logout }

在Symfony 4中,您可以在您的routes.yaml中添加此内容

logout:
    path: /logout
    controller: L3\Bundle\CasBundle\Controller\LogoutController::logoutAction

在Symfony 5或Symfony6或Symfony7中,您必须在应用程序的DefaultController中创建一个注销路由

    /**
     * @Route("/logout", name="logout")
     */
    public function logoutAction() {
        if (($this->getParameter('cas_logout_target') !== null) && (!empty($this->getParameter('cas_logout_target')))) {
            \phpCAS::client(CAS_VERSION_2_0, $this->getParameter('host'), $this->getParameter('port'), is_null($this->getParameter('path')) ? '' : $this->getParameter('path'), true);
            \phpCAS::logoutWithRedirectService($this->getParameter('cas_logout_target'));
        } else {
            \phpCAS::client(CAS_VERSION_2_0, $this->getParameter('host'), $this->getParameter('port'), is_null($this->getParameter('path')) ? '' : $this->getParameter('path'), true);
            \phpCAS::logout();
        }
    }

注销处理器

在某些应用程序(如EasyAdminBundle)中,您可能需要使用注销成功处理器,以便EasyAdmin使用此注销成功处理器进行/注销。

  • 创建src/Handler/AuthenticationHandler.php,并添加以下代码
<?php

namespace App\Handler;

use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Http\Logout\LogoutSuccessHandlerInterface;

class AuthenticationHandler implements LogoutSuccessHandlerInterface
{
    protected $cas_logout_target;

    public function __construct($cas_logout_target)
    {
        $this->cas_logout_target = $cas_logout_target;
    }

    public function onLogoutSuccess(Request $request) : Response
    {
        if(!empty($this->cas_logout_target)) {
            \phpCAS::logoutWithRedirectService($this->cas_logout_target);
        } else {
            \phpCAS::logout();
        }
    }
}
  • 在config/services.yaml中,在"services:"下添加此行
     authentication_handler:
         class: App\Handler\AuthenticationHandler
         arguments: ['%cas_logout_target%']
         public: false
  • 在config/packages/security.yaml中,添加以下行(对于firewalls下的cas: true)
             logout:
                 path: /logout
                 success_handler: authentication_handler
                 invalidate_session: false

附加属性

Jasig Cas服务器可以通过phpCAS::getAttributes()函数返回除主要属性(通常是uid)之外的附加属性。

您可以使用以下代码在控制器中获取附加属性

...
$attributes = $this->get('security.token_storage')->getToken()->getAttributes();
...

对于Symfony6

...
$attributes = $this->container->get('security.token_storage')->getToken()->getAttributes();
...

注释

如果您安装了此包,则Route注释会运行

composer require doctrine/annotations