Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the process of integrating phpCAS with Laravel

2025-03-26 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

Laravel integration of phpCAS process is how, many novices are not very clear about this, in order to help you solve this problem, the following editor will explain for you in detail, people with this need can come to learn, I hope you can gain something.

Trample Notes of Laravel Integrated phpCAS

CAS is a popular single sign-on protocol. Php version of client phpCAS is officially provided. So far, its coding style has remained in the PEAR era, even the namespace has not been used. Fortunately, phpCAS supports the introduction of composer, and there is no problem with the introduction of several Laravel projects. however, in the past two days, there is a project that needs to change from stand-alone deployment to multi-machine deployment. I never expected to step on some holes here. Record it here.

Callback pit

When jumping to CAS Server for authentication, it is found that the incoming callback address has been added to port 8080. Because it is a multi-machine deployment, the access request will first go through the load balancer (Ali Cloud SLB) and then reach the web server, and this 8080 is the listening port of the web server.

Then we trace the logic of the callback address generated by phpCAS and find that there is a code like this:

If (empty ($_ SERVER ['HTTP_X_FORWARDED_PORT'])) {$server_port = $_ SERVER [' SERVER_PORT'];} else {$ports = explode (',', $_ SERVER ['HTTP_X_FORWARDED_PORT']); $server_port = $ports [0];}

Aliyun's SLB will not be passed to the backend server X-FORWARDED-PORT, the http header, so phpCAS will get $_ SERVER ['SERVER_PORT'], which is port 8080 of nginx.

Fortunately, phpCAS provides the setFixedServiceURL function, which allows us to manually set the callback address:

PhpCAS::setFixedServiceURL ($request- > url ())

The callback address is normal, but when it is returned from CAS Server to client, it is told that ticket is invalid.

Continue to check the log and code, and find that you are negligent here. When CAS Server returns to the client side, the url of the page is http://client/login?ticket=xxxxx, and when the client side uses ticket to exchange user information from server, you also need to bring the callback address (service) when applying for the ticket. The server side will verify whether the ticket and service are consistent, and the service when applying for ticket should be http://client/login, so we need to remove the ticket parameter in url.

PhpCAS::setFixedServiceURL ($this- > getUrlWithoutTicket ($request))

The getUrlWithoutTicket function is as follows:

Private function getUrlWithoutTicket (Request $request) {$query = parse_query ($request- > getQueryString ()); unset ($query ['ticket']); $question = $request- > getBaseUrl (). $request- > getPathInfo () = =' /'?'/':'?'; return $query? $request- > url (). $question.http_build_query ($query): $request- > url ();} Session pit

This is a phpCAS + Laravel combination pit, which makes you lose your temper again and again.

PHP defaults to Session storage and files, so a very important point of changing from single machine to multi-machine is to deal with Session sharing. The solution is also very simple, that is, change the Session storage mode from files to redis/memecache/database and so on.

Laravel provides these driver by default, so excitedly changed the .env file to change SESSION_DRIVER to redis. Pull it online and find that it doesn't work. PhpCAS's change to the $_ SESSION variable has not been written into redis. What's going on?

So I chased the Session implementation of Laravel and found that it was not imagined to use session_set_save_handler to register Session read and write logic, that is to say, Laravel's Session actually did not modify the php's $_ SESSION read and write logic, directly manipulating $_ SESSION or the default behavior of walking (reading and writing local files).

Well, fortunately, several SessionDriver of Laravel implement the SessionHandlerInterface interface, so we can call session_set_save_handler ourselves:

Session_set_save_handler (app (StartSession::class)-> getSession ($request)-> getHandler ())

I didn't expect to report the wrong report!

Session_write_close (): Session callback expects true/false return value

I chased the Laravel code and found that the write method of redis driver's parent class, Illuminate\ Session\ CacheBasedSessionHandler, returned void. So I mentioned that a PR was going to be repaired, but I didn't expect to be rejected. It turned out that someone had repaired it before and was revert, saying that it would cause the server to get stuck, but I didn't find a specific issue.

Well, both memcache and redis inherit this parent class, so I'll have to try database instead.

Session_write_close did not report wrong this time, but there is still a problem with CAS login, constantly jumping between CAS server and callback url. So I chased the log and code all the way, and found that the destroy method of the database driver class Illuminate\ Session\ DatabaseSessionHandler did not mark the $this- > exists attribute as false after destroying the Session, while phpCAS has a logic of renameSession.

$old_session = $_ SESSION;session_destroy (); $session_id = preg_replace ('/ [^ a-zA-Z0-9\ -] /',', $ticket); session_id ($session_id); session_start (); $_ SESSION = $old_session

The consequence is that the sql of the operation session table corresponding to $_ SESSION = $old_session; executes update instead of insert, which means that the session data cannot be written to the session table!

I really have no choice but to write a Session Wrapper to deal with it.

From the above two cases, redis driver is easier to deal with, as long as you can return true when calling the write method. So the code is as follows

Namespace App\ Services;use SessionHandlerInterface;class MySession implements SessionHandlerInterface {/ * * @ var SessionHandlerInterface * / protected $realHdl; / * Session constructor. * @ param SessionHandlerInterface $realHdl * / public function _ construct (SessionHandlerInterface $realHdl) {$this- > realHdl = $realHdl;} public function close () {return $this- > realHdl- > close ();} public function destroy ($session_id) {return $this- > realHdl- > destroy ($session_id);} public function gc ($maxlifetime) {return $this- > realHdl- > gc ($maxlifetime) } public function open ($save_path, $name) {return $this- > realHdl- > open ($save_path, $name);} public function read ($session_id) {return $this- > realHdl- > read ($session_id)?:';} public function write ($session_id, $session_data) {$this- > realHdl- > write ($session_id, $session_data); return true; / / here}}

Then call session_set_save_handler to become

Session_set_save_handler (new MySession (app (StartSession::class)-> getSession ($request)-> getHandler ()); is it helpful for you to read the above? If you want to know more about the relevant knowledge or read more related articles, please follow the industry information channel, thank you for your support.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report