• Ajax——CORS跨域共享


    一、同源政策

    同源政策的目的

    二、CORS:跨域资源共享

    CORS:跨域资源共享(Cross-origin resource sharing),它允许浏览器向跨域服务器发送ajax请求,克服了ajax只能同源使用的限制

    当浏览器发现请求是跨域请求时,会在自动请求头加入origin字段,服务器端会根据origin字段的值来决定是否同意这次请求

    如果服务器端同意这次请求,就会在响应头中加入 Access-Control-Access-Origin字段

    origin:http://localhost:3000
     Access-Control-Allow-Origin: 'http://localhost:3000'
     Access-Control-Allow-Origin: '*'    // *代表允许所有客户端访问这个服务器端

     2.1、在服务器端设置可以跨域访问的路由地址

    准备两个服务器s1和s2,在s1中写入下面的代码,点击按钮发起请求

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <button id="btn">点我发送请求</button>
        <script src="./js/ajax.js"></script>
        <script>
            // 获取按钮
            var btn = document.getElementById('btn');
            // 为按钮添加点击事件
            btn.onclick =function(){
                ajax({
                    type:'get',
                    url:'http://localhost:3001/cross',
                    success:function(data){
                        console.log(data);
                        
                    }
                })
            }
        </script>
    </body>
    </html>

    在s2服务器的app.js中写入下面的代码

    app.get('/cross',(req,res)=>{
        // 1.允许哪些客户端访问
        // * 代表允许所有客户端访问我
        res.header('Access-Control-Allow-Origin', '*')
        // 2. 允许客户端使用哪些请求方法访问我
        res.header('Access-Control-Allow-Methods', 'get,post')
        res.send('ok')
    })

    可以在控制台中看到输出了OK

    但是当请求比较多的时候,我们没有办法筛选哪些可以访问哪些不能访问

    改写成下面的样子

    //拦截所有请求
    app.use((req,res,next)=>{
        // 1.允许哪些客户端访问
        // * 代表允许所有客户端访问我
        res.header('Access-Control-Allow-Origin', '*')
        // 2. 允许客户端使用哪些请求方法访问我
        res.header('Access-Control-Allow-Methods', 'get,post')
        next();
    })
    app.get(
    '/cross',(req,res)=>{ res.send('ok') })

    2.2、服务器端解决跨域

    设置多个服务器,由于服务器互相访问是没有同原限制的,借助这个解决跨域

    A客户端访问A服务器端

    使用request模块实现A服务器端访问B服务器端的数据

    B服务器端响应数据给A服务器端,再响应给A客户端

    <body>
        <button id="btn">点我发送请求</button>
        <script src="./js/ajax.js"></script>
        <script>
            // 获取按钮
            var btn = document.getElementById('btn');
            // 为按钮添加点击事件
            btn.onclick =function(){
                ajax({
                    type:'get',
                    url:'http://localhost:3000/server',
                    success:function(data){
                        console.log(data);
                        
                    }
                })
            }
        </script>
    </body>
    // 向其他服务器端请求数据的模块,服务器端是没有同源政策的限制的,可以向任何服务器发送请求
    const request = require('request');
    
    // 第一个参数是其他服务器端的地址,第二个参数是一个回调函数,当请求返回数据的时候,这个回调函数开始执行
    // 回调函数第一个参数err:如果请求发生错误会返回错误信息,否则返回null
    // response:是一个对象,
    // body: 返回的是响应内容
    app.get('/server', (req, res) => {
        request('http://localhost:3001/cross', (err, response, body) => {
            res.send(body)
        })
    })

    2.3、cookie跨域问题

     实现客户端与服务器端识别身份的一种技术

    客户端第一次访问服务器端的时候,服务器端响应的时候会发送一个身份证,也就是cookie,这个cookie就会存储在客户端的浏览器中,等客户端下一次再次访问这个服务器端的时候,cookie会随着请求被自动发送到服务器端,服务器端拿到cookie就知道客户端是谁了

    但是一旦涉及到跨域,出于安全考虑,防止信息被窃取,cookie就不会随着请求被发送到服务器端了,也就是说,在跨域的情况下发起的ajax请求,是不会携带cookie信息的

    解决这个问题我们需要设置如下属性:

    Access-Control-Allow-Credentials:true  //允许客户端发送请求时携带cookie
    ajax对象下面的withCredentials属性,默认值为false
     
    案例:
    有一个登录模块:
    <div class="container">
            <form id="loginForm">
                <div class="form-group">
                    <label>用户名</label>
                    <input type="text" name="username" class="form-control" placeholder="请输入用户名">
                </div>
                <div class="form-group">
                    <label>密码</label>
                    <input type="password" name="password" class="form-control" placeholder="请输入用密码">
                </div>
                <input type="button" class="btn btn-default" value="登录" id="loginBtn">
                <input type="button" class="btn btn-default" value="检测用户登录状态" id="checkLogin">
            </form>
        </div>

    第一步:获取登录按钮和检测登录按钮一级登录表单,使用formData

    第二步:添加点击事件,点击按钮发送请求

    第三步:在客户端设置属性,由于是跨域请求,我们需要设置withCredentials属性的值

    // 获取登录按钮
        var loginBtn = document.getElementById('loginBtn');
        // 获取检测登录状态按钮
        var checkLogin = document.getElementById('checkLogin');
        // 获取登录表单
        var loginForm = document.getElementById('loginForm');
        // 为登录按钮添加点击事件
        loginBtn.onclick = function(){
            // 将HTML表单转换为formData表单对象
            var formData = new FormData(loginForm);
            // 创建ajax对象
            var xhr = new XMLHttpRequest();
            // 对ajax对象进行配置
            xhr.open('post','http://localhost:3001/login');
            // 当发送跨域请求时,携带cookie信息
            xhr.withCredentials = true;
            //  发送请求并传递请求参数
            xhr.send(formData)
            // 监听服务器端的响应
            xhr.onload = function(){
                console.log(xhr.responseText);
                
            }
    
        }
    
        // 当检测登录按钮被点击时
        checkLogin.onclick = function(){
            // 创建ajax对象
            var xhr = new XMLHttpRequest();
            // 对ajax对象进行配置
            xhr.open('get','http://localhost:3001/checkLogin');
            // 当发送跨域请求时,携带cookie信息
            xhr.withCredentials = true;
            //  发送请求并传递请求参数
            xhr.send()
            // 监听服务器端的响应
            xhr.onload = function(){
                console.log(xhr.responseText);
                
            }
        }

     第四步:在服务器端设置相关属性

    // 拦截所有请求
    app.use((req, res, next) => {
        // 1.允许哪些客户端访问我
        // * 代表允许所有的客户端访问我
        // 注意:如果跨域请求中涉及到cookie信息传递,值不可以为*号 比如是具体的域名信息
        res.header('Access-Control-Allow-Origin', 'http://localhost:3000')
        // 2.允许客户端使用哪些请求方法访问我
        res.header('Access-Control-Allow-Methods', 'get,post')
        // 允许客户端发送跨域请求时携带cookie信息
        res.header('Access-Control-Allow-Credentials', true);
        next();
    });
  • 相关阅读:
    css3 flex
    多行文本溢出 显示... 判断是否多行文本溢出
    事件多次执行
    WinForm布局
    winform 公共控件
    WinForm窗体菜单和工具栏
    2017-4-24WinForm 基础
    2017-4-20实体类,数据访问类.字符串攻击.防攻击
    ADO.net增删改查
    类库,通用变量,is/as运算符,委托。
  • 原文地址:https://www.cnblogs.com/ccv2/p/12814203.html
Copyright © 2020-2023  润新知