PHP multi-site sharing seeion to achieve single sign-on

I haven't had anything to do recently, sum up and sort out the problems of single sign-on.

The basic principle of single sign-on is: the client shares the sesionid, and the server shares the session information. By obtaining the same session information on the server side through a common sessionid, you can achieve the purpose of single sign-on (that is, multi-site sharing of user information, one login is available everywhere).

Single sign-on is divided into two situations:

1. The site is deployed on the same server and uses the same second-level domain name

In this case, it is better to solve.

1. First, solve the problem of sharing the site in the client's sessionid (in the cookie). Use the ini_set() function to specify the domain of the cookie, as follows: ini_set('session.cookie_domain', '.xxxx.com');//Set the domain of the server cookie, xxxx is the public second-level domain name
2. Secondly, it solves the sharing of session information of the site on the server side. Because the site is on the same server, the generated session file is public, and the corresponding session information can be obtained directly by using the sessionid.

2. The site is deployed on different servers and uses different domain names (multi-iFrame jump mode)

This situation is more complicated, because the site uses different domain names on different servers, and the ini_set cannot be used to set the scope of the cookie on the client side. On the server side, they also generate their own session files, which cannot be shared, but the solution is still used.

1. Solve the client sessionid synchronization problem first.

Suppose we have three sites, the domain names are aa.com, bb.com, cc.com. We set up a common login entry login.php on aa.com, and all login requests from the three websites jump to this page. The code flow is as follows:

	$back = login($name,$pwd);//执行登陆操作,成功就写入session
    //如果登录成功,进行以下操作流程
    if($back){
        $sessionid = session_id();
        $key = encode($session,$keyword);//生成安全码
        //输出一个登陆成功提示页,并跳转到请求登陆的站点
    }

Add the following code to the html prompt page of successful login, and use the iframe tag to request the sites that need to be logged in synchronously.
Write picture description here
The set_cookie.php files of the aa.com and cc.com sites are as follows

//解密$key
decode($key);
//把当前站点的sessionid设置为传递的sessionid
session_id($_GET['sessionid']);
session_start();
2. Solve the problem of sharing sessions on the server side of the three sites.

As mentioned earlier, because the three sites are not on the same server, they will generate their own session files. If you want to share these files, you will face a series of cross-domain problems. So we changed our thinking, instead of using files to save session information, we save the session information in the database. In this way, as long as the sessionid of the session information is obtained, any site can access the same session information.

We create a mysql_session.php file to store session information in the database, the code is as follows

$gb_DBname="test";                        //数据库名称 
$gb_DBuser="root";                        //数据库用户名称 
$gb_DBpass="";                            //数据库密码 
$gb_DBHOSTname="127.0.0.1";               //主机的名称或是IP地址 
$SESS_DBH="";                           //数据库对象
session_module_name("User");            //定义session存储按用户定义的方式
$SESS_LIFE=get_cfg_var("session.gc_maxlifetime");//得到session的最大有效期,也可以自定义
 
function sess_open($save_path,$session_name)
{ 
    global $gb_DBHOSTname,$gb_DBname,$gb_DBuser,$gb_DBpass,$SESS_DBH; 
    if(!$SESS_DBH=mysql_pconnect($gb_DBHOSTname,$gb_DBuser,$gb_DBpass)){ 
    echo "MySql Error:".mysql_error().""; 
    die(); 
    } 
    if(!mysql_select_db($gb_DBname,$SESS_DBH)){ 
    echo "MySql Error:".mysql_error().""; 
    die(); 
    } 
    return true; 
} 
function sess_close(){ 
return true; 
} 
function sess_read($key)
{ 
    global $SESS_DBH,$SESS_LIFE; 
    $qry="select value from db_session where sesskey = '$key' and expiry > ".time(); 
    $qid=mysql_query($qry,$SESS_DBH); 
    if(list($value)=mysql_fetch_row($qid)){ 
    return $value; 
    } 
    return false; 
}
 
//写入session信息。保存session信息的数据表名为:db_session
//除了主键自增id,需要的字段如下
//sesskey   sessionid
//values    session值
//expiry    session的到期日期
 
function sess_write($key,$val)
{ 
    global $SESS_DBH,$SESS_LIFE; 
    $expiry=time()+$SESS_LIFE; 
    $value=$val; 
    $qry="insert into db_session values('$key',$expiry,'$value')"; 
    $qid=mysql_query($qry,$SESS_DBH); 
    if(!$qid){ 
    $qry="update db_session set expiry=$expiry, value='$value' where sesskey='$key' and expiry >".time(); 
    $qid=mysql_query($qry,$SESS_DBH); 
    } 
    return $qid; 
} 
function sess_destroy($key)
{ 
    global $SESS_DBH; 
    $qry="delete from db_session where sesskey = '$key'"; 
    $qid=mysql_query($qry,$SESS_DBH); 
    return $qid; 
} 
function sess_gc($maxlifetime)
{ 
    global $SESS_DBH; 
    $qry="delete from db_session where expiry < ".time(); 
    $qid=mysql_query($qry,$SESS_DBH); 
    return mysql_affected_rows($SESS_DBH); 
} 
 
session_set_save_handler("sess_open","sess_close","sess_read","sess_write","sess_destroy","sess_gc");

Afterwards, in the page that needs to use the session, import the file before session_start(), and the rest is the same as usual seesion. You will find that the session you assigned has been stored in the database.

3. The site is deployed on different servers and uses different domain names (CAS mode)

In the second method, when a site is logged in, we set the cookie of several other sites that need to be logged in synchronously to the same value through the iframe, and the same sessionid value can be queried from the database, which realizes single sign-on .
The disadvantage is that when there are many sites, it is necessary to add iframes and other codes one by one, which is not convenient for expansion.
At this time we can use the CAS mode, the basic process is as follows:

1. The user accesses the app system. The app system needs to log in, but the user is not logged in now.
2. Jump to the CAS server (with the URL of the app system as the sso jumpback address), that is, the SSO login system. From now on, the CAS Server in the figure will be collectively called the SSO system. The SSO system is also not logged in, and the user login page pops up.
3. The user fills in the user name and password. After the SSO system authenticates, the login status is written into the SSO session, and the browser (Browser) is written into the cookie under the SSO domain.
4. After the SSO system login is completed, an ST (Service Ticket) will be generated, then jump to the app system, and at the same time pass the ST as a parameter to the app system.
5. After the app system gets the ST, it sends a request to the SSO from the background to verify whether the ST is valid.
6. After the verification is passed, the app system writes the login status into the session and sets the Cookie under the app domain.

At this point, the cross-domain single sign-on is complete. When we access the app system in the future, the app is logged in. Next, let's take a look at the process when accessing the app2 system.

1. The user accesses the app2 system, and the app2 system is not logged in, and jumps to SSO.
2. After the app system requests SSO to log in to the system, the browser has already recorded the cookie value of the SSO system. At this time, the SSO system has been logged in, and there is no need to log in again for authentication.
3. SSO generates ST, the browser jumps to app2 system, and passes ST to app2 as a parameter.
4. App2 gets the ST and accesses the SSO in the background to verify whether the ST is valid.
5. After the verification is successful, app2 writes the login status into the session, and writes cookies under the domain of app2.

In this way, the app2 system does not need to go through the login process, it is already logged in. SSO, app and app2 are in different domains, so it’s okay if the session between them is not shared.

Some students asked me that after logging in to the SSO system, when I jumped back to the original business system, they brought a parameter ST, and the business system had to use ST to visit SSO again for verification. I felt that this step was a bit redundant. He thought that after the SSO login authentication is passed, the user information is returned to the original business system through the callback address, and the original business system directly sets the login status, so the process is simple and the login is completed. Isn't it good?

In fact, this problem is very serious. If I do not log in in SSO, but directly type in the callback address in the browser and bring forged user information, does the business system think that I am logged in? This is terrible.

Guess you like

Origin blog.csdn.net/u012830303/article/details/82252708