专业编程基础技术教程

网站首页 > 基础教程 正文

面试常客系列之跨域 java跨域面试题

ccvgpt 2024-10-12 13:41:13 基础教程 7 ℃

前言

跨域?什么是跨域呢?我们先来看看一个url的组成,http://192.x.x:3000/home,这一个url我们可以分成四部分来看http是协议,192.x.x是域名,3000是端口,home是路径.在浏览器中,我们从一个域名发送请求到另一个域名,如果两个域名的协议,域名,端口三部分只要存在一部分不同就会发生跨域,也就是说只有两个域名的协议,域名,端口都相同才会不会发生跨域,所以我们又如何解决跨域的问题呢?在下文中会给大家介绍几种方法去解决跨域问题.

正文

那么要解决跨域就不得不谈及同源策略,同源策略是一种安全措施,用于防止恶意网站通过脚本获取或修改其他网站的数据.只要协议,域名,端口,三者其中一个不一致,在请求响应过程中就会触发同源策略.

面试常客系列之跨域 java跨域面试题

JSONP

第一种方式是JSONP,但是跟JSON并没有关系,这只是一种称呼.那么JSONP的实现原理也是非常简单的,我们来想想,平时我们在页面加载图片时<img src="" alt="">是不是可以正常加载页面,我们的scr里面是放的地址,这里是需要发送请求的,如果按照跨域的说法,这里势必会发生跨域,但是事实上这里并没有发生跨域,图片依旧可以正常加载.原因是如果加载图片一直需要解决跨域的话,就会很麻烦,索性就把src放进了“白名单”不会发生跨域,类似的<link rel="stylesheet" href="">,<script src=""></script>都不会发生跨域,因此JSONP的过程就采取了这个方式.

我们在JS中创建一个script的标签,并设置src属性并插入到html中就可以了.但是这样我们就无法操作接口请求发送响应获取到的数据了,这里我们就需要打造一下.

<!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>
     <script>
        function jsonp(url,cb){
            return new Promise((resolve,reject)=>{
                const script = document.createElement('script')

                window[cb] = function(data){
                    resolve(data)
                }

                script.src = `${url}?cb=${cb}`
                document.body.appendChild(script) 
            })
        }
        jsonp('http://localhost:3000','callback').then(res=>{
            console.log(res);
        })
     </script>
</body>
</html>

window[cb]是我们在全局声明了一个叫cb的函数.拿到响应返回的数据我们借助了new Promise来处理异步请求,并使用resolve()传递数据.在后端操作可能就比较绕了.

const http = require('http');

http.createServer(function (req, res){
    const query = new URL(req.url,`http://${req.headers.host}`).searchParams
    console.log(query);
    if(query.get('cb')){
        const cb = query.get('cb')
        const data = 'hello world'
        const result = `${cb}("${data}")`
        res.end(result)
    }
}).listen(3000)

new URL(req.url,`http://${req.headers.host}`).searchParams是获取到请求携带的参数,这里返回的是一个map对象,所以取值我们用的是get(key).
const cb = query.get('cb') :获取到携带的参数callback 这里 cb = callback
const data = 'hello world':实参,传给函数
const result = `${cb}("${data}"):这里就会比较绕了,首先cb是指callback,这里加上()就变成一个函数的样子callback(),data实参,就变成了callback("hello world")再使用res.end(),这里浏览器就是把这个函数给执行了.也就是把这一串执行了

window[cb] = function(data){
                    resolve(data)
            }

总的来说JSONP的操作原理就是借助script的标签的src属性不受同源策略的影响,来发送请求,给后端携带一个参数callback 并在前端定义callback函数体,后端返回callback 的调用形式并将要影响的值作为callback,当浏览器接受到响应后,就会触发全局的callback函数,从而让callback以参数的形式接收到后端的响应.

cors

使用cors处理同源,这个用一句话说明就是通过在后端代码中,操作http响应头添加‘Access-Control-Allow-Origin’字段,来限制任意url不会被同源策略操作,从而达到解决跨域. 前端代码:

<!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>
    <script>
        const xhr = new XMLHttpRequest();//创建一个ajax
        xhr.open('GET', 'http://localhost:3000', true); // 建立一个GET请求
        xhr.send();
        xhr.onreadystatechange = function() {
            if(xhr.readyState === 4 && xhr.status === 200){
                console.log(xhr.responseText);
            }
        }
    </script>
</body>
</html>

后端代码:

const http = require('http');

http.createServer(function (req, res){
    res.writeHead(200, {
        'Access-Control-Allow-Origin': '*',
        // 'accept-control-allow-methods':
    });
    res.end('hello world')
}).listen(3000)

我们操作这一个字段Access-Control-Allow-Origin,设置哪一个源可以跨域,这里*是指所有的源都可以.

nginx

image.png

其实nginx的原理就是代理,当发送请求过程中会被nginx代码后再到接受请求,然后在响应的过程中,也会在nginx中被代理后再返回出去.这个nginx主要用于项目部署到服务器上时使用的.

WebSocket

scoket协议天生不受同源策略的影响这一点就非常的厉害,那么它的作用是什么呢?它是双端管道,信息是双向传递的,不用只有一发送了请求,才会响应信息给你.

我们可以这张极其简陋的图,这里A随时发消息给B,B不做请求也可以也接收到,A不作出请求,B也可以随时发消息给A.

我们先在终端使用npm init -y初始化一下一个后端项目,并npm i ws

这里我们使用的WebScoket协议而不是HTTP协议

<!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>
    <script>
        function myWebSocket(url,params={}) {
            return new Promise((resolve,reject)=>{
                const socket = new WebSocket()
                socket.onopen = ()=>{
                    socket.send(JSON.stringify(params))
                }
                socket.onmessage = (e)=>{
                    resolve(e.data)
                }
            })
        }
        myWebSocket('ws://localhost:3000',{age:18}).then(res=>{
            console.log(res);
        })
    </script>
</body>
</html>

这里需要注意的是WebScoket只能接受字符串数据,所以这里socket.send(JSON.stringify(params))我们要处理一下处理的类型.

后端我们需要监听连接事件。当连接后我们就要监听信息

const webSocket = require('ws')

const ws = new webSocket.Server({port:3000})
ws.on('connection',function(obj){
    obj.on('message',function(data){
        obj.send('hello world')
    })
})

监听到了信息就将可以操作返回信息出去了.

以上就是解决跨域问题的几个常见的方法,希望对大家有所帮助!!感谢大家阅读

原文:https://juejin.cn/post/7412831382957211688

作者:Virtual09

#记录我的9月生活#

Tags:

最近发表
标签列表