PHP Single Sign-On 구현 솔루션의 예

黄舟
풀어 주다: 2023-03-06 07:52:01
원래의
1313명이 탐색했습니다.

요약:

이 기사에서는 주로 웹 서비스, 세션 및 쿠키 기술을 사용하는 범용 싱글 사인온 시스템의 분석 및 설계를 소개합니다. 구체적인 구현 언어는 PHP입니다. 영어로 Single Sign On, 줄여서 SSO라고도 하는 Single Sign-On은 현재 기업과 네트워크 비즈니스에서 사용자를 포괄적으로 처리하는 데 중요한 부분입니다. SSO의 정의는 여러 응용 프로그램 시스템에서 사용자가 한 번만 로그인하면 상호 신뢰되는 모든 응용 프로그램 시스템에 액세스할 수 있다는 것입니다.

동기:

ucenter의 전체 사이트 로그인 방식을 사용해 본 친구들은 이것이 전형적인 관찰자 패턴 솔루션이라는 것을 알아야 합니다. 사용자 센터는 주체이며 관찰자의 등록 및 삭제는 ucenter 백엔드에서 통합됩니다. 각 하위 응용 프로그램 사이트는 관찰자에 해당합니다. 사용자 센터의 모든 로그인 작업은 js 스크립트를 트리거하여 w3c 표준 하위 사이트 로그인 인터페이스(api/uc.php)를 다시 호출합니다.

이 방법의 단점은 크게 두 가지라고 생각합니다. 1. 하위 사이트가 너무 많으면 그에 따라 콜백 인터페이스도 늘어나게 됩니다. 이는 배포되는 하위 사이트 수의 제한 때문입니다. .로그인 효율성이 너무 낮고 파악하기 어렵지 않도록 제어하는 ​​방법 2. 특정 변전소의 콜백 인터페이스에 문제가 발생하면 기본 로그인 프로세스가 중단됩니다(로그인 프로그램의 실행 시간). 제한될 수 있으나 해당 문제가 있을 경우 변전소 뒤에 있는 변전소의 콜백 인터페이스는 더 이상 호출되지 않습니다.

위 문제를 토대로 실제 개발 과정에서 또 하나의 사인을 디자인했습니다. -on 시스템

1. 로그인 원칙 설명

Single Sign-On의 기술적 구현 메커니즘: 사용자가 처음으로 애플리케이션 시스템 1에 액세스할 때 아직 로그인하지 않은 경우 사용자가 제공한 로그인 정보를 기반으로 로그인하도록 인증 시스템으로 이동하며, 인증 시스템은 신원 확인을 수행하고, 유효성 검사를 통과하면 인증 자격 증명을 반환해야 합니다. 사용자가 다른 애플리케이션에 액세스할 때 애플리케이션 시스템이 요청을 받은 후 이 티켓을 자신의 인증 자격 증명으로 가져옵니다. 확인을 위해 인증 시스템으로 이동하여 티켓의 유효성을 확인합니다. 인증을 통과하면 사용자는 다시 로그인하지 않고도 응용시스템 2와 응용시스템 3에 접근할 수 있다.

SSO를 구현하려면 다음과 같은 주요 기능이 필요함을 알 수 있다.

a ) 모든 신청 시스템은 신원 인증 시스템을 공유합니다.

b) 모든 신청 시스템은 티켓 정보를 식별하고 추출할 수 있습니다.

c) 신청 시스템은 로그인한 사용자를 식별하고 자동으로 현재 사용자가 로그인했는지 확인하여 Single Sign-On 기능을 완료합니다

위의 기본 원칙을 기반으로 PHP 언어로 Single Sign-On 시스템 프로그램 세트를 설계하여 이제 공식 프로덕션 서버 운영. 이 시스템 프로그램은 전체 시스템의 고유한 세션 ID를 가진 티켓 정보를 매체로 사용하여 현재 온라인 사용자의 전체 사이트 정보(로그인 상태 정보 및 기타 처리해야 할 사용자 전체 사이트 정보)를 얻습니다.

2. 프로세스 설명:

로그인 프로세스:

처음으로 사이트에 로그인:

a) 사용자는 사용자 이름 + 비밀번호를 입력하고 사용자 인증 센터에 로그인 요청을 보냅니다

b) 현재 사이트에 로그인하면 웹 서비스 요청을 통해 사용자 인증 센터에서 사용자 이름의 정당성을 확인하고 비밀번호. 검증에 성공하면 현재 세션의 사용자를 식별하는 티켓이 생성되고, 현재 로그인된 하위 사이트의 사이트 식별자가 사용자 센터에 기록됩니다. 사용자 데이터와 하위 사이트 티켓을 얻었습니다. 확인에 실패하면 해당 오류 상태 코드가 반환됩니다.

d) 이전 단계의 웹 서비스 요청에서 반환된 결과에 따라 현재 하위 사이트는 사용자에 로그인합니다. 상태 코드가 성공을 나타내면 현재 사이트는 이 쿠키를 통해 티켓을 저장합니다. 사이트는 사용자의 로그인 상태를 기록합니다. 상태 코드가 실패를 나타내는 경우 사용자에게 해당 로그인 실패 프롬프트가 표시됩니다.

2. 로그인하면 사용자는 다른 하위 섹션으로 이동합니다:

a) 사이트의 쿠키 또는 세션을 통해 사용자의 로그인 상태를 확인합니다. 확인이 통과되면 일반을 입력합니다. 그렇지 않으면 사용자 센터에서 사용자의 로그인 상태를 확인합니다(사용자 확인 센터에 티켓을 보냅니다). 확인에 성공하면 반환된 사용자 정보에 대해 로컬 로그인 처리가 수행됩니다. 로그인되지 않았습니다.


로그아웃 과정
a) 현재 로그아웃 사이트는 해당 사이트의 사용자 로그인 상태와 로컬에 저장된 전체 사이트의 고유한 임의 ID를 삭제합니다

b) 웹서비스 인터페이스를 통해 사이트 전체에 기록된 고유 랜덤 ID를 삭제합니다. 웹 서비스 인터페이스가 반환되고 로그인된 다른 하위 사이트의 자바스크립트 코드가 로그아웃되며 이 사이트에서 이 코드가 출력됩니다.

c) js 코드는 해당 사이트의 W3C 표준 로그아웃 스크립트에 액세스합니다


3. 코드 설명:
본 기사에 포함된 관련 코드 관심이 있으시면 이 기사 끝에 있는 다운로드 링크를 클릭하여 다운로드하실 수 있습니다.

1. 로그인 프로세스:

브라우저를 열 때부터 로그인한 첫 번째 하위 사이트는 UClientSSO::loginSSO() 메서드를 호출해야 합니다. 이 방법은 전체 사이트에 고유하고 사용자를 식별하는 데 사용되는 임의의 ID를 반환합니다. 이 임의 ID는 이 웹사이트의 쿠키를 통해 UClientSSO::loginSSO()에 저장되었습니다. 즉, 하위 사이트는 이 웹사이트에 대한 사용자 로그인 ID의 스텁을 유지합니다.

a) UClientSSO::loginSSO() 메소드는 다음과 같습니다.


<?php
/**
 * 用户验证中心 登陆用户处理
 *
 * @param string $username   - 用户名
 * @param string $password   - 用户原始密码
 * @param boolean $remember   - 是否永久记住登陆账号
 * @param boolean $alreadyEnc  - 传入的密码是否已经经过simpleEncPass加密过
 *
 * @return array  - integer $return[&#39;status&#39;] 大于 0:返回用户 ID,表示用户登录成功
 *                        -1:用户不存在,或者被删除
 *                        -2:密码错
 *                                                 -11:验证码错误
 *                     string $return[&#39;username&#39;]   : 用户名
 *                     string $return[&#39;password&#39;]   : 密码
 *                     string $return[&#39;email&#39;]    : Email
 */

static public function loginSSO($username, $password, $remember=false, $alreadyEnc=false) {
self::_init();
self::_removeLocalSid();
$ret = array();

//
//1. 处理传入webservice接口的参数
//
$_params = array(
        &#39;username&#39; => $username,
        &#39;password&#39; => $alreadyEnc ? trim($password) : self::simpleEncPass(trim($password)),
        &#39;ip&#39;    => self::onlineip(),
        &#39;siteFlag&#39; => self::$site,
        &#39;remember&#39; => $remember
);
$_params[&#39;checksum&#39;] = self::_getCheckSum($_params[&#39;username&#39;] . $_params[&#39;password&#39;] .
$_params[&#39;ip&#39;] . $_params[&#39;siteFlag&#39;] . $_params[&#39;remember&#39;]);

//
// 2.调用webservice接口,进行登陆处理
//
$aRet = self::_callSoap(&#39;loginUCenter&#39;, $_params);

if (intval($aRet[&#39;resultFlag&#39;]) > 0 && $aRet[&#39;sessID&#39;]) {
//成功登陆
//设置本地session id
self::_setLocalSid($aRet[&#39;sessID&#39;]);

//设置用户中心的统一session id脚本路径
self::$_synloginScript = urldecode($aRet[&#39;script&#39;]);

$ret = $aRet[&#39;userinfo&#39;];
} else {

$ret[&#39;status&#39;] = $aRet[&#39;resultFlag&#39;];
}

return $ret;
}//end of function         

//b) 用户验证中心的webservice服务程序,接收到登陆验证请求后,调用UCenter::loginUCenter()方法来处理登陆请求。
/**
* 用户验证中心 登陆用户处理
*
* @param string $username
* @param string $password
* @param string $ip
* @param string $checksum
* @return array
*/
static public function loginUCenter($username, $password, $ip, $siteFlag, $remember=false) {
self::_init();
session_start();
$ret = array();
$arr_login_res   = login_user($username, $password, $ip);
$res_login     = $arr_login_res[&#39;status&#39;];        //
$ret[&#39;resultFlag&#39;] = $res_login;

if ($res_login < 1) {
//登陆失败
} else {

//登陆成功
$_SESSION[self::$_ucSessKey] = $arr_login_res;

$_SESSION[self::$_ucSessKey][&#39;salt&#39;] =
self::_getUserPassSalt($_SESSION[self::$_ucSessKey][&#39;username&#39;], $_SESSION[self::$_ucSessKey][&#39;password&#39;]);

$ret[&#39;userinfo&#39;] = $_SESSION[self::$_ucSessKey];
$ret[&#39;sessID&#39;]  = session_id();    //生成全站的唯一session id,作为ticket全站通行

//
//合作中心站回调登陆接口(设置用户中心的统一session id)
//
self::_createCoSitesInfo();
$uinfo = array();
$_timestamp = time();
$_rawCode = array(
            &#39;action&#39; => &#39;setSid&#39;,
            &#39;sid&#39;  => $ret[&#39;sessID&#39;],
            &#39;time&#39;  => $_timestamp,
);
if ($remember) {
$uinfo = array(
                &#39;remember&#39; => 1,
                &#39;username&#39; => $username,
                &#39;password&#39; => $password
);
}

$ret[&#39;script&#39;] = &#39;&#39;;
$_rawStr = http_build_query(array_merge($_rawCode, $uinfo));

//
// 合作站点的全域cookie设置脚本地址
//
foreach ((array)self::$_coSitesInfo as $_siteInfo) {
$_code = self::authcode($_rawStr, &#39;ENCODE&#39;, $_siteInfo[&#39;key&#39;]);
$_src = $_siteInfo[&#39;url&#39;] . &#39;?code=&#39; . $_code . &#39;&time=&#39; . $_timestamp;
$ret[&#39;script&#39;] .= urlencode(&#39;&#39;);
}

//
// 记住已登陆战
//
self::registerLoggedSite($siteFlag, $ret[&#39;sessID&#39;]);

unset($ret[&#39;userinfo&#39;][&#39;salt&#39;]);
}

return $ret;
}

?>
로그인 후 복사



2. 웹사이트 로그인 성공 후 현지화된 사용자 로그인 처리가 수행되며, 후속 사용자 로그인 여부 확인은 로컬에서만 수행됩니다. (로그인한 사용자 상태 정보에 대한 로컬 접속을 위해서는 브라우저를 닫은 후 종료되도록 설정해 주세요.)

3. 사용자의 로그인 상태 감지 시, 로컬 인증에 실패할 경우 먼저 로컬 인증 과정을 호출해 주세요. , 다시 호출 UClientSSO::checkUserLogin() 메서드는 사용자 센터로 이동하여 사용자의 로그인 상태를 감지합니다.

a) UClientSSO::checkUserLogin() 메서드는 다음과 같습니다.

<?php
 /**
 * 用户单点登陆验证函数
 *
 * @return array  - integer $return[&#39;status&#39;] 大于 0:返回用户 ID,表示用户登录成功
 *                                                  0:用户没有在全站登陆
 *                        -1:用户不存在,或者被删除
 *                        -2:密码错
 *                        -3:未进行过单点登陆处理
 *                                                 -11:验证码错误
 *                     string $return[&#39;username&#39;]   : 用户名
 *                     string $return[&#39;password&#39;]   : 密码
 *                     string $return[&#39;email&#39;]    : Email
 */
 public static function checkUserLogin(){
 self::_init();
 $ret = array();
 $_sessId = self::_getLocalSid();
 if (empty($_sessId)) {
 //永久记住账号处理
 if(isset($_COOKIE[_UC_USER_COOKIE_NAME]) && !empty($_COOKIE[_UC_USER_COOKIE_NAME])) {
 
 //
 // 根据cookie里的用户名和密码判断用户是否已经登陆。
 //
 $_userinfo = explode(&#39;|g|&#39;, self::authcode($_COOKIE[_UC_USER_COOKIE_NAME], &#39;DECODE&#39;, self::$_authcodeKey));
 
 $username = $_userinfo[0];
 $password = isset($_userinfo[1]) ? $_userinfo[1] : &#39;&#39;;
 if (empty($password)) {
 $ret[&#39;status&#39;] = -3;
 } else {
 return self::loginSSO($username, $password, true, true);
 }
 
 } else {
 $ret[&#39;status&#39;] = -3;
 }
 
 } else {
 //
 //本站原先已经登陆过,通过保留的sesson id存根去用户中心验证
 //
 $_params = array(
             &#39;sessId&#39;  => $_sessId,
             &#39;siteFlag&#39; => self::$site,
             &#39;checksum&#39; => md5($_sessId . self::$site . self::$_mcComunicationKey)
 );
 $aRet = self::_callSoap(&#39;getOnlineUser&#39;, $_params);
 if (intval($aRet[&#39;resultFlag&#39;]) > 0) {
 //成功登陆
 $ret = $aRet[&#39;userinfo&#39;];
 } else {
 $ret[&#39;status&#39;] = $aRet[&#39;resultFlag&#39;];
 }
 }
 
 return $ret;
 }       
 
 b) 用户验证中心的webservice服务程序,接收到检验登陆的请求后,调用UCenter::getOnlineUser()方法来处理登陆请求:
 [php]/**
 * 根据sid,获取当前登陆的用户信息
 *
 * @param string $sessId    - 全站唯一session id,用做ticket
 * @return array
 */
 /**
 * 根据sid,获取当前登陆的用户信息
 *
 * @param string $sessId    - 全站唯一session id,用做ticket
 * @return array
 */
 static public function getOnlineUser($sessId, $siteFlag) {
 self::_init();
 session_id(trim($sessId));
 session_start();
 
 $ret = array();
 $_userinfo = $_SESSION[self::$_ucSessKey];
 
 if (isset($_userinfo[&#39;username&#39;]) && isset($_userinfo[&#39;password&#39;]) &&
 self::_getUserPassSalt($_userinfo[&#39;username&#39;], $_userinfo[&#39;password&#39;])) {
 $ret[&#39;resultFlag&#39;] = "1";
 $ret[&#39;userinfo&#39;] = $_userinfo;
 
 self::registerLoggedSite($siteFlag, $sessId);        //记住已登陆战
 unset($ret[&#39;userinfo&#39;][&#39;salt&#39;]);
 } else {
 $ret[&#39;resultFlag&#39;] = "0";
 }
 
 return ($ret);
 }
 ?>
로그인 후 복사



4. 싱글 로그아웃 중에 UClientSSO를 호출합니다:: 로그아웃SSO( ) 메소드. 호출 성공 후 로그인된 다른 사이트를 즉시 로그아웃시키려면 UClientSSO::getSynloginScript() 메소드를 호출하여 W3C 표준 스크립트를 얻어 페이지에 출력하세요.

a) UClientSSO::logoutSSO() 메소드는 다음과 같습니다:

<?php
/**
* 全站单点登出
* - 通过webservice请求注销掉用户的全站唯一标识
*
* @return integer  1: 成功
*                   -11:验证码错误
*/
public static function logoutSSO(){
    self::_init();
    $_sessId = self::_getLocalSid();
    //
    //本站没有登陆的话,不让同步登出其他站
    //
    if (empty($_sessId)) {
        self::_initSess(true);
        return false;
    }
    $_params = array(
        &#39;sessId&#39;  => $_sessId,
        &#39;siteFlag&#39; => self::$site,
        &#39;checksum&#39; => md5($_sessId . self::$site . self::$_mcComunicationKey)
    );
    $aRet = self::_callSoap(&#39;logoutUCenter&#39;, $_params);
    if (intval($aRet[&#39;resultFlag&#39;]) > 0) {
        //成功登出
        self::_removeLocalSid();        //移除本站记录的sid存根
        self::$_synlogoutScript = urldecode($aRet[&#39;script&#39;]);
        $ret = 1;
    } else {
        $ret = $aRet[&#39;resultFlag&#39;];
    }
    return intval($ret);
}          [/php]
    b) 用户验证中心的webservice服务程序,接收到全站登出请求后,调用UCenter::loginUCenter()方法来处理登陆请求:
/**
* 登出全站处理
*
* @param string - 全站唯一session id,用做ticket
* @return boolean
*/
static public function logoutUCenter($sessId) {
    self::_init();
    session_id(trim($sessId));
    session_start();
    $_SESSION = array();
    return empty($_SESSION) ? true : false;
}
?>
로그인 후 복사



4 코드 배포:

1. 사용자 인증 센터 설정

a) 사용자 인증 센터에서 서브스테이션에 제공하는 웹 서비스 서비스 인터페이스 파일인 UserSvc.php는 호스트 이름/webapps/port/에 배포됩니다. UserSvc.php. wsdl 콘텐츠를 보려면 http://www.php.cn/UserSvc.php?wsdl

을 방문하세요. b) 사용자 센터 사용자 단일 지점 서비스 클래스 파일은 UCenterSSO.class.php이며 파일은 경로는 호스트 이름/webapps/include/UCenterSSO.class.php에 있습니다. 이 파일은 사용자 Single Sign-In 처리를 위한 서버 클래스이며, 호스트 이름/webapps/port/UserSvc.php에 의해 호출됩니다. 사용자의 로그인 정보, Single Sign-In, Single Sign-Out 처리 상태 정보 등을 얻기 위해 사용됩니다.

c) 사용자 인증 센터는 W3C 표준을 통과하며 쿠키를 사용하여 기록합니다. 전체 사이트에서 사용자의 고유 임의 ID를 삭제하는 스크립트 파일은 호스트 이름/webapps/port/cookie_mgr.php입니다.

2 하위 사이트 설정 <<>
A) uclientsso.class.php는 사용자 센터의 서비스 클라이언트 디렉터리에 배포됩니다. 배포 후 UClientSSO::setSite('1'); 의 마지막 줄을 수정하세요. 매개변수 값은 사용자 인증 센터에서 각 사이트에 균일하게 할당한 식별 ID입니다.

b) 클라이언트에 서비스를 제공합니다. 배포된 사용자 센터 패키지 아래 api 디렉토리에서 logout_sso.php 스크립트를 여기에 전송하고 이 사이트에서 로그아웃하기 위한 처리 스크립트를 작성하십시오.

c) 하위 사이트의 사용자 로그인 상태를 확인하는 코드 섹션에는 사용자 센터의 추가 Single Sign-On 확인 처리가 추가됩니다.

즉, 먼저 이 사이트를 통해 사용자의 로그인 상태를 확인하세요. 확인에 실패하면 사용자 센터에 가서 확인하세요. 확인 작업을 수행하려면 UClientSSO::checkUserLogin() 인터페이스를 호출해야 합니다. 인터페이스의 의미는 코드 설명을 참조하세요.

d) 지점 스테이션의 로그아웃 처리 스크립트에서 UClientSSO::getSynlogoutScript()를 사용하여 스크립트 문자열 출력을 얻습니다.


5. 확장 기능:
1. 모든 온라인 사용자를 기록하고 추적합니다.

모든 사용자 로그인은 사용자 인증 센터를 거쳐야 하기 때문에 users 티켓은 인증센터에서 생성되며, 메모리 테이블에 있는 티켓(세션 ID)과 사용자 사이에 매핑 테이블이 구축될 수 있습니다. 모든 온라인 사용자의 기록 목록을 가져옵니다.

향후 다른 기능을 구현하기 위해 사용자 상태를 추적해야 하는 경우 이 매핑 테이블을 추적하면 됩니다. 다른 기능으로는 온라인 사용자 목록 획득, 사용자의 온라인 상태 확인, 온라인 사용자 수 획득 등이 있습니다.

2. 특수통계처리

시스템 전체의 로그인과 로그아웃은 반드시 이용자 인증센터를 거쳐야 하기 때문에 이용자에 대한 특수한 통계처리가 가능합니다. 일별 사용자 로그인 수, 로그인 시간, 로그인 상태 만료 시간, 기간별 온라인 사용자 수 추세 등


6. 기타 사항:                                                                                                          브라우저를 닫으면 상태가 손실됩니다. 각 지점 사이트는 다음과 같이 세션이나 쿠키를 처리해야 합니다.
a) 세션 모드에서 사용자 로그인 상태를 기록하는 사이트
사이트의 공개 스크립트 시작 부분에 다음 코드를 추가하세요


<?php
 session_write_close();
 ini_set(&#39;session.auto_start&#39;, 0);          //关闭session自动启动
 ini_set(&#39;session.cookie_lifetime&#39;, 0);      //设置session在浏览器关闭时失效
 ini_set(&#39;session.gc_maxlifetime&#39;, 3600); //session在浏览器未关闭时的持续存活时间   
 ?>
로그인 후 복사



b) 사용자 로그인 상태를 기록하기 위해 쿠키를 사용하는 사이트

사용자 로그인에 대한 쿠키 설정 시 쿠키 유효 기간을 null로 설정하세요. status.

위 내용은 PHP 버전의 Single Sign-In 구현 솔루션 예시 내용입니다. 자세한 내용은 PHP 중국어 홈페이지(www. php.cn)!




-->

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!