Cross domain problem of session in ThinkPHP

Time:2020-10-27

Problem description

In “ThinkPHP realizing sms verification and registration”, Xiaobian not only records the implementation method of SMS verification code, but also records the implementation method of image verification code.
When the back-end project and front-end project are deployed to the server, everything is normal; after the back-end project is deployed to the server and cross domain access is allowed, the local front-end project uses the back-end project interface on the server, and the problem arises
First of all, use the postman test to obtain the image captcha interface and verify the image captcha interface, normal.
Then, use the interface to get image captcha in HTML, which is normal; finally, use the interface of verifying image captcha in JS, error!!!

analysis

Through the description of the problem, we can see that the problem appears in the cross domain. So, there are two possibilities, one is because the cross domain settings are incorrect; the other is because of ThinkPHP itself.

With another cross domain configuration, the problem remains. That’s the problem of ThinkPHP itself. After searching the data, the problem is located on the cross domain of ThinkPHP session.

Cross domain solution

In fact, both ThinkPHP and PHP itself need to be set when solving the cross domain problem of session session.cookie_ domain。
There are several solutions to the problem of cross domain session
The first case: if there is no. Htaccess file in the directory, that is, if the URL pseudo-static is not taken, then in conf/ config.php Add:

ini_ set(' session.cookie_ domain',". domain.com "); // cross domain access to session

At this point, if you turn on debugging, you can use it! But if you turn off debugging, it doesn’t work!

Second, if you have. Htaccess in your directory, then you are in the root directory, index.php Add:

<?php ini_ set(' session.cookie_ domain',". domain.com "); // cross domain access to session
//Application entry file
?>

This method whether open or not debugging work!

However, our problem is not cross domain, but completely cross domain, so the above method is invalid.

Full cross domain solution

Get picture captcha request

To view the request information for obtaining the image captcha, the request headers are as follows:

Accept:image/webp,image/*,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch
Accept-Language:zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4
Connection:keep-alive
Cookie:pma_lang=zh_CN; pma_collation_connection=utf8_unicode_ci; pma_iv-1=wnpO4gv0eQRW1AMHmGr2ww%3D%3D; pmaUser-1=weZPqS0%2BW7nzFUVHRdqcfA%3D%3D
Host:api.voidking.com
Referer:http://localhost/ajax/ajax.html
User-Agent:Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36

Response headers are:

Access-Control-Allow-Origin:*
Cache-Control:post-check=0, pre-check=0
Cache-Control:private, max-age=0, no-store, no-cache, must-revalidate
Connection:keep-alive
Content-Type:image/png
Date:Sun, 27 Nov 2016 12:10:44 GMT
Expires:Thu, 19 Nov 1981 08:52:00 GMT
Pragma:no-cache
Server:nginx
Set-Cookie:PHPSESSID=721t4sqanvsii550m1dk8gq1o3; path=/; domain=.voidking.com
Transfer-Encoding:chunked

Verification code request

To view the request information of the verification code, the request headers are:

Accept:application/json, text/javascript, */*; q=0.01
Accept-Encoding:gzip, deflate
Accept-Language:zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4
Connection:keep-alive
Content-Length:9
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
Host:api.voidking.com
Origin:http://localhost
Referer:http://localhost/ajax/ajax.html
User-Agent:Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36

Response headers are:

Access-Control-Allow-Origin:*
Cache-Control:no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection:keep-alive
Content-Encoding:gzip
Content-Type:text/html; charset=UTF-8
Date:Sun, 27 Nov 2016 12:13:21 GMT
Expires:Thu, 19 Nov 1981 08:52:00 GMT
Pragma:no-cache
Server:nginx
Set-Cookie:PHPSESSID=149t0hhs2icqaaemvp39onkgp4; path=/; domain=.voidking.com
Transfer-Encoding:chunked
Vary:Accept-Encoding

Get picture captcha request again

Request headers are:

Accept:image/webp,image/*,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch
Accept-Language:zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4
Cache-Control:max-age=0
Connection:keep-alive
Cookie:pma_lang=zh_CN; pma_collation_connection=utf8_unicode_ci; pma_iv-1=wnpO4gv0eQRW1AMHmGr2ww%3D%3D; pmaUser-1=weZPqS0%2BW7nzFUVHRdqcfA%3D%3D; PHPSESSID=721t4sqanvsii550m1dk8gq1o3
Host:api.voidking.com
Referer:http://localhost/ajax/ajax.html
User-Agent:Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36

Response headers are:

Access-Control-Allow-Origin:*
Cache-Control:private, max-age=0, no-store, no-cache, must-revalidate
Cache-Control:post-check=0, pre-check=0
Connection:keep-alive
Content-Type:image/png
Date:Sun, 27 Nov 2016 13:26:21 GMT
Expires:Thu, 19 Nov 1981 08:52:00 GMT
Pragma:no-cache
Server:nginx
Transfer-Encoding:chunked

Comparison of three requests

Cross domain problem of session in ThinkPHP

For the first time, there is no phpsessid in the cookie, so there is set cookie in the returned information. For the second time, the cookie contains phpsessid. Therefore, there is no set cookie in the returned information. Moreover, the phpsessid in the information set cookie returned by the first request is the same as the phpsessid in the second request request request information cookie.

The Ajax request for verifying the image verification code does not have a cookie, and naturally there is no phpsessid. Therefore, the returned information also contains set cookie.

It can be seen that we need to make some changes in the front end so that the request can be sent with a cookie.

Front end jQuery settings

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>jquery</title>
</head>
<body>
    <p>
        <img>
        <input type="text" id="picCode">
        < input type = button "id = send" value = verify ">
    </p>
<script></script>
<script>
    $(function(){
        $('#send').click(function(){
            //console.log(document.cookie);
            $.ajax({
                url: 'http://api.voidking.com/owner-bd/index.php/Home/CheckCode/checkPicCode',
                type: 'POST',
                crossDomain: true,
                xhrFields: {
                    withCredentials: true
                },
                dataType: 'json',
                data: {code: $('#picCode').val()},
                success: function(data){
                    console.log(data);
                },
                error: function(xhr){
                    console.log(xhr);
                }
            });
        });
    });
</script>
</body>
</html>

The error in the request is as follows:

A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'http://localhost' is therefore not allowed access. The credentials mode of an XMLHttpRequest is controlled by the withCredentials attribute.

Cross domain error is reported. It can be seen that the back-end needs to be modified to receive cross domain cookies.

Back end nginx settings

add_header Access-Control-Allow-Origin http://localhost;
add_header Access-Control-Allow-Credentials true;

be careful:
When the server-side access control allow credentials parameter is true, the value of the access control allow origin parameter cannot be *.

After the back-end nginx is set, the Ajax request of jQuery is normal and can carry cookies. The back-end normally receives data and returns data.

Since angular’s Ajax request is different from jQuery, we also need to study how angular sends cross domain requests with cookies.

Front end angular settings

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>angular</title>
    <script></script>
</head>
<body ng-app="myApp" >
    <p ng-controller="myCtrl">
        <img>
        <input type="text" id="picCode" ng-model="picCode">
        < input type = "button" ng Click = "send()" value = verify ">
    </p>
<script>
    var app = angular.module('myApp', []);
    app.controller('myCtrl', function($scope, $http, $httpParamSerializer) {
        $scope.send = function(){
            $http({
                method:'POST',
                url:'http://api.voidking.com/owner-bd/index.php/Home/CheckCode/checkPicCode',
                headers:{
                    'Content-Type':'application/x-www-form-urlencoded'
                },
                withCredentials: true,
                dataType: 'json',
                data: $httpParamSerializer({code: $scope.picCode})
            }).then(function successCallback(response) {
                console.log(response.data);
                $scope.username = response.data.username;
            }, function errorCallback(response) {
                console.log(response.data);
            });
        }
    });
</script>

</body>
</html>

Postscript

At this point, it is completed and the cross domain problem of session is solved perfectly.

bookmark

Solution to cross domain problem of session implemented by ThinkPHP framework
http://www.jb51.net/article/5…

Session sharing of ThinkPHP secondary domain name
http://www.thinkphp.cn/topic/…

PHP cross domain, cross sub domain, cross server read session
http://blog.csdn.net/kylinbl/…

Four methods of cross server session sharing
http://blog.sina.com.cn/s/blo…

Angular realizes cross domain scheme through CORS
https://my.oschina.net/blogsh…