nginx和阿里云全站加速允许api服务跨域的方法

需求:

1.好比我们有个api是https://api.class4ever.com

2.但是用别的域名调用这个应的api,不能访问, 浏览器说不能跨域

解决方法如下

如果没有使用CDN和全站加速, 那么在nginx中配置;

在nginx的api服务的配置文件的合适位置添加如下代码

    add_header 'Access-Control-Allow-Origin' '*';
    add_header 'Access-Control-Allow-Credentials' 'true';
    add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS';

如下图

如果使用了全站加速/CDN, 那么在nginx中配置就不好使了,

需要在全站加速/CDN控制台里配置, 配置如下两项就可以了

前端跨域登录演示

是把token分别保存至不同域名的localStorage

主站登录页 http://www.main.com/login.html:

<!DOCTYPE html>
<html lang="zh-cn">

<head>
    <meta charset="utf-8">
    <title>跨域登录演示</title>
    <link rel="stylesheet" href="//static.class4ever.com/layui/v2.5.5/css/layui.css">
    <style>
        [v-cloak] {
            display: none;
        }
    </style>
</head>

<body>
    <div id="app" v-cloak>
        <table class="layui-table" style="width:400px;margin:100px auto;">
            <tr>
                <td colspan="2">
                    <h2>
                        跨域登录演示
                    </h2>
                </td>
            </tr>
            <tr>
                <td>用户名</td>
                <td>{{ username }}</td>
            </tr>
            <tr>
                <td>token</td>
                <td>
                    <input v-model="token" class="layui-input" type="text">
                </td>
            </tr>
            <tr>
                <td>登录结果</td>
                <td id="log" style="color:blue;"></td>
            </tr>
            <tr>
                <td colspan="2">
                    <button @click="login" class="layui-btn layui-btn-normal">登录</button>
                </td>
            </tr>
        </table>

        <iframe v-for="(domain,k) in cross_domain_list" :name="'_cross_domain_' + k"
            :src="domain + '/cross_domain.html'" style="display: none;"></iframe>
    </div>
</body>
<script src="//static.class4ever.com/jquery/jquery-3.4.1.min.js"></script>
<script src="//static.class4ever.com/vuejs/v2.6.12/vue.min.js"></script>

<script>
    const app = new Vue({
        el: '#app',
        data: {
            /* 
               跨域的域名列表:
                  1. 不包含本页所在的域名
                  2. 协议名要正确
                  3. 须在该域名下配置/cross_domain.html
            */
            cross_domain_list: [
                'http://www.a.com',
                'http://www.b.com'
            ],

            username: '小明',
            token: '测试token',

            //登录过程
            login_success: 0,
        },
        mounted: function () {
            /* 监听收到的消息 */
            window.addEventListener('message', function (e) {
                let res = e.data;
                if (res.code === 200) {
                    let key = res.data.domain_key
                    let domain = app.cross_domain_list[key]

                    app.log(domain + ' 已登录<br>')

                    if (++app.login_success === app.cross_domain_list.length)
                        app.log('所有域名都已登录')
                }
            }, false);
        },
        methods: {
            /* 登录初始化 */
            login_init: function () {
                this.login_success = 0

                $('#log').empty()
            },


            /* 记录日志 */
            log: function (str) {
                $('#log').append(str)
            },


            /* 本域名登录 */
            self_login: function () {
                localStorage.setItem('username', this.username);
                localStorage.setItem('token', this.token);

                let protocol = window.location.protocol
                let domain = window.location.host

                $('#log').append(protocol + '://' + domain + ' 已登录<br>')
            },


            /* 跨域登录 */
            cross_login: function () {
                var domain_list = this.cross_domain_list
                for (let key in domain_list) {
                    let data = {
                        domain_key: key,
                        username: this.username,
                        token: this.token
                    }

                    let name = '_cross_domain_' + key

                    window.frames[name].postMessage(data, domain_list[key]);
                }
            },


            /* 
              测试登录: 
                向其他所有域名发送token
            */
            login: function () {
                this.login_init()

                this.self_login()

                this.cross_login()
            }
        }
    })
</script>

</html>

再给除主站外, 要跨站登录的域名分别配置/cross_domain.html:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
</head>

<body></body>
<script>
    window.addEventListener('message', function (e) {
        if (e.source != window.parent)
            return;

        //保存用户名和token        
        localStorage.setItem('username', e.data.username);
        localStorage.setItem('token', e.data.token);

        let res = {
            code: 200,
            message: 'success',
            data: {
                domain_key: e.data.domain_key
            }
        }

        window.parent.postMessage(res, '*');
    }, false);
</script>

</html>

利用iframe跨域写localStorage的范例

a.com/index_a.html:

<!DOCTYPE html>
<html lang="zh-cn">

<head>
    <meta charset="UTF-8">
    <title>cross domain</title>
</head>

<body>
    <h2>Status</h2>
    <p></p>
    <a href="http://b.com/index_b.html">去index_b查看结果</a>
    <iframe src="https://b.com/getmessage.html" frameborder="0" style="width:0;height:0;"></iframe>
    <script>
        window.onload = function () {
            //在页面加载完成后主页面向iframe发送请求
            window.frames[0].postMessage('跨域存储', 'http://b.com');
        }

        // 主页面监听message事件,
        window.addEventListener('message', function (e) {
            var data = e.data;
            document.querySelector('p').innerHTML = data;
        }, false);
    </script>
</body>

</html>

b.com/getmessage.html:

<!DOCTYPE html>
<html lang="zh-cn">

<head>
    <meta charset="UTF-8">
    <title>getmessage</title>
</head>

<body>
    <script>
        //iframe接收消息,并把当前颜色发送给主页面  
        window.addEventListener('message', function (e) {
            if (e.source != window.parent)
                return;
            console.log(e.data);
            localStorage.setItem('task', e.data);

            window.parent.postMessage('finished', '*');
        }, false);
    </script>
</body>

</html>

b.com/index_b.html:

<!DOCTYPE html>
<html lang="zh-cn">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>

<body>
    <div>点击获取任务</div>
    <p></p>
    <script>
        document.querySelector('div').addEventListener('click', function () {
            document.querySelector('p').innerHTML = localStorage.getItem('task');
        }, false);
    </script>
</body>

</html>

借此思想可实现跨域登录

参考文献:

https://www.jianshu.com/p/e86d92aeae69/