【Java】解決跨域問題的三種方案

本篇博客會介紹前後端分離項目如何實現跨域請求。

CORS(Cross-Origin Resource Sharing)問題的出現主要是因爲瀏覽器的同源策略,同源的要求是:同協議,同IP,同端口。即不能在非同源情況下進行請求,實際上是爲了保護用戶的安全。
在這裏插入圖片描述
首先,準備一下frontend和backend的代碼。這裏爲了創造非同源條件,前端跑在本機的8080端口下,後端跑在本機的8000端口下。

  1. 前端利用yarn創建的項目,webpack-dev-server作爲服務器。前端項目結構和主要代碼如下:在這裏插入圖片描述
    package.json
{
  "name": "website",
  "version": "1.0.0",
  "main": "y",
  "license": "MIT",
  "scripts": {
    "build": "webpack",
    "start": "webpack-dev-server --port '8080'"
  },
  "dependencies": {
    "axios": "^0.19.1",
    "axios-jsonp-pro": "^1.1.7",
    "css-loader": "^3.4.2",
    "element-ui": "^2.13.0",
    "file-loader": "^5.0.2",
    "style-loader": "^1.1.3",
    "ts-loader": "^6.2.1",
    "typescript": "^3.7.5",
    "vue": "^2.6.11",
    "vue-loader": "^15.8.3",
    "vue-style-loader": "^4.1.2",
    "vue-template-compiler": "^2.6.11",
    "webpack": "^4.41.5",
    "webpack-cli": "^3.3.10",
    "webpack-dev-server": "^3.10.1"
  }
}

webpack.config.js

const Vlp = require('vue-loader/lib/plugin');
const path = require('path');

module.exports = {

    entry: './src/main.js',

    output: {
        path: path.resolve(__dirname, './dist'),
        filename: 'main.js'
    },

    mode: 'development',

    module: {
        rules: [
            {
                test: /\.vue$/,
                loader: 'vue-loader'
            },
            {
                test: /\.css$/,
                loader: 'style-loader!css-loader'
            },
            {
                test: /.(eot|woff|woff2|ttf)([\\\\\\\\?]?.*)$/,
                loader: "file-loader"
            }
        ]
    },

    plugins: [
        new Vlp()
    ]

}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    
    <div id="app"></div>

    <script src="./dist/main.js"></script>
</body>
</html>

main.js

import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import app from './pages/app.vue';

Vue.use(ElementUI);

new Vue({
    el: '#app',
    render: h => h(app)
});

pages/app.vue

<template>
  <div>

  </div>
</template>

<style scoped>
</style>

<script>
export default {
};
</script>
  1. 後端新建了一個springboot項目,只改動了入口文件和配置了端口。

SeckillApplication.java

package com.example.seckill;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
@SpringBootApplication
public class SeckillApplication {

	@GetMapping("/test")
	public String test() {
		return "hello";
	}

	public static void main(String[] args) {
		SpringApplication.run(SeckillApplication.class, args);
	}

}

一、JSONP

jsonp的原理其實是<script>標籤不受同源策略的限制,即src屬性的值可以和當前站點非同源。使用jsonp可以通過jquery來實現,也推薦大家使用axios-jsonpaxios-jsonp-pro,通過yarn add axios-jsonp即可安裝,詳細用法可以訪問 yarn官網。只需要改動pages/app.vue即可。

<script>
import axios from 'axios-jsonp-pro';

export default {
  created: function() {
    axios
      .jsonp("http://127.0.0.1:8000/api/test")
      .then(result => {console.log(result)})
      .catch(err => {console.log(err.message)});
  }
};
</script>

請求成功,我們能看到我們需要的字符串hello
在這裏插入圖片描述

二、後端跨域規則

  1. 首先我們使用axios進行網絡請求,該組件沒有跨域功能。
<script>
import axios from "axios";


export default {

  created: function() {
    axios.get('http://127.0.0.1:8000/api/test')
    	.then(response=>{console.log(response)});
};
</script>
  1. 我們只需要在方法上添加註解@CrossOrigin,並設定允許進行跨域請求的地址,即可。
	@GetMapping("/test")
	@CrossOrigin(origins = {"http://127.0.0.1:8080", "http://localhost:8080"})
	public String test() {
		return "hello";
	}

在這裏插入圖片描述

三、使用Nginx進行反向代理

我們對請求進行規定,以/api/開頭的請求都交給後端服務器,以/開頭的請求交給前端服務器,實現代理即可。下面是nginx配置文件,注意先後順序。

nginx.conf

	server {
		listen 127.0.0.1:80;
		location /api/ {
			proxy_pass http://127.0.0.1:8000; 
		}
		location / {
			proxy_pass http://127.0.0.1:8080;
		}
	}

重啓nginx服務後,我們需要對前端代碼進行改寫,後段代碼去掉@CrossOrigin註解即可。

<script>
import axios from "axios";


export default {
  created: function() {
    axios.get('/api/test').then(response=>{console.log(response)});
  }
};
</script>

我們直接通過Nginx服務器訪問http://127.0.0.1即可。
在這裏插入圖片描述

四、請求時添加請求頭

這種方法較爲簡單,按照瀏覽器提示添加相應的請求頭即可,這裏不做演示。

五、總結

本次試驗中有大量的多餘代碼,請讀者自行忽略。另外,復現的時候有幾點需要注意:

  1. 前端項目每次都需要執行yarn run build先編譯,再yarn run start啓動項目。
  2. 停止項目時需要先按Ctrl + D,再按Ctrl + C才能停止項目,不然下次啓動時會提示端口占用。
  3. 需要即時清除瀏覽器緩存。
發佈了73 篇原創文章 · 獲贊 282 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章