Django前后端打通

news2024/12/23 12:36:00

跨域问题

【 0 】前言

image-20240511083754769

​ 同源策略(Same Origin Policy)是浏览器安全策略的重要组成部分,它限制了来自不同源的网页之间的数据交互,以防止恶意攻击。当一个网页尝试执行与它的源(即协议、域名和端口)不一致的请求时,浏览器会出于安全考虑拦截这个请求。

​ 跨域资源共享(CORS, Cross-Origin Resource Sharing)是一个W3C规范,它允许某些跨源请求,如Ajax,从而克服了Ajax只能同源使用的限制。CORS需要浏览器和服务器同时支持,基本思想是使用自定义的HTTP头来让浏览器和服务器进行通信。

​ 在Django项目中解决跨域问题,可以通过多种方法,包括手动编写中间件以及使用第三方库。你给出的示例展示了如何手动编写一个CORS中间件,以及如何使用django-cors-headers这个流行的第三方库来简化CORS的设置。

手动编写CORS中间件

​ 中间件代码示例中,通过向响应头中添加适当的CORS相关头部,允许来自任何源的请求("Access-Control-Allow-Origin": "*")。同时,对于OPTIONS请求(预检请求),该中间件还允许所有的方法和头部。

使用django-cors-headers

  1. 安装库:pip install django-cors-headers
  2. settings.py中添加'corsheaders'INSTALLED_APPS
  3. settings.pyMIDDLEWARE中添加'corsheaders.middleware.CorsMiddleware',并确保它在其他中间件之前(特别是在CommonMiddleware之前)。
  4. 配置CORS选项。例如,设置CORS_ORIGIN_ALLOW_ALLTrue来允许所有源的请求,或者你可以指定一个允许源的列表。CORS_ALLOW_METHODSCORS_ALLOW_HEADERS分别定义了允许的HTTP方法和头部。

​ 请注意,出于安全考虑,通常不建议在生产环境中设置CORS_ORIGIN_ALLOW_ALLTrue,除非你完全理解可能的安全风险。在生产环境中,最好明确指定允许的源。

​ 另外,值得注意的是,虽然CORS解决了浏览器端的跨域问题,但服务器端仍然需要验证请求的有效性,以防止潜在的安全威胁,如CSRF攻击。因此,即使启用了CORS,也不应忽视服务器端的安全性措施。

# 同源策略(Same origin policy)是一种约定,它规定了 请求的url地址,必须与浏览器上的url地址处于同域上,也就是域名,端口,协议相同,如果不一致,请求会发送成功,后端会正常响应,但是浏览器会拦截


#  浏览器对非同源请求返回的结果做了拦截
# 只要做前后端分离,就会出跨域



# 解决跨域问题
	-CORS :跨域资源共享  咱们讲的方式   向响应头中加数据,允许跨域
    	- 后端代码处理
        - nginx代理
    -JSONP :利用有的标签没有跨域问题 script  img
    -websocket:长链接,不存在跨域
    -前端代理:开发阶段用,上线不用
    
    
# cors如何解决跨域
	-需要服务端支持---》就是服务端再响应头中加数据即可
    
# CORS基本流程
	CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)
	简单请求,只发送一次:
    非简单请求发送两次,第一次是OPTIONS预检请求,第二次是真正的请求
# 什么是简单,什么是非简单
#请求方法是以下三种方法之一:
    HEAD
    GET
    POST
# HTTP的头信息不超出以下几种字段:
    Accept
    Accept-Language
    Content-Language
    Last-Event-ID
    Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
    
# 请求头中带了 token ,所有请求都是非简单



### 解决跨域---统一写个中间件--》处理所有跨域
from django.utils.deprecation import MiddlewareMixin
class CorsMiddleWare(MiddlewareMixin):
    def process_response(self,request,response):
        if request.method=="OPTIONS":
            #可以加*
            response["Access-Control-Allow-Headers"]="*"
            res['Access-Control-Allow-Methods'] = '*'
        response["Access-Control-Allow-Origin"] = "*"
        return response
	
    
# 第三方解决方案
	# 1、使用pip安装
	pip install django-cors-headers
    #2、添加到setting的app中
    INSTALLED_APPS = (
        ...
        'corsheaders',
        ...
    )
  #3、添加中间件
    MIDDLEWARE = [  
        ...
        'corsheaders.middleware.CorsMiddleware',
        ...
    ]
4、setting下面添加下面的配置
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_METHODS = (
	'DELETE',
	'GET',
	'OPTIONS',
	'PATCH',
	'POST',
	'PUT',
	'VIEW',
)

CORS_ALLOW_HEADERS = (
	'XMLHttpRequest',
	'X_FILENAME',
	'accept-encoding',
	'authorization',
	'content-type',
	'dnt',
	'origin',
	'user-agent',
	'x-csrftoken',
	'x-requested-with',
	'Pragma',
	'token'
)

【 1 】解释

Access-Control-Allow-HeadersAccess-Control-Allow-MethodsAccess-Control-Allow-Origin 是三个与跨源资源共享(CORS)相关的 HTTP 响应头。它们各自有不同的作用和使用方法。

1. Access-Control-Allow-Origin

作用

  • 用于指定哪些源(域名、协议和端口)有权限访问该资源。

使用方法

  • 如果服务器希望允许来自特定源的请求,如 https://example.com,可以返回以下响应头:
Access-Control-Allow-Origin: https://example.com
  • 如果服务器希望允许来自任何源的请求(这通常在生产环境中是不安全的),可以返回:
Access-Control-Allow-Origin: *

2. Access-Control-Allow-Methods

作用

  • 列出哪些 HTTP 方法(如 GET、POST、PUT、DELETE 等)允许跨源请求。

使用方法

  • 如果服务器只允许 GET 和 POST 方法,可以返回以下响应头:
Access-Control-Allow-Methods: GET, POST
  • 这个响应头通常与预检请求(OPTIONS 请求)一起使用,以检查服务器是否允许跨源请求中使用的特定 HTTP 方法。

3. Access-Control-Allow-Headers

作用

  • 用于告知浏览器在跨域请求中,所允许的请求头字段(Request Header)。

使用方法

  • 如果浏览器请求包括 Access-Control-Request-Headers 字段,则 Access-Control-Allow-Headers 字段是必需的。它的值是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在“预检”中请求的字段。
  • 例如,如果服务器允许跨域请求时使用的请求头字段是 Content-TypeAuthorization,可以返回以下响应头:
Access-Control-Allow-Headers: Content-Type, Authorization

总结

  • Access-Control-Allow-Origin 用于指定哪些源可以访问资源。
  • Access-Control-Allow-Methods 用于指定哪些 HTTP 方法允许跨源请求。
  • Access-Control-Allow-Headers 用于告知浏览器在跨域请求中,所允许的请求头字段。

​ 这三个响应头通常一起使用,以确保跨源请求的安全性和可访问性。同时,它们也遵循 CORS 规范,确保浏览器和服务器之间的正确交互。

【 2 】跨域问题

【 1 】笨办法

  • Access-Control-Allow-Origin

  • 在子路由的视图类

from rest_framework.views import APIView
from lufy.utils.utils_response import APIResponse 	

class CoreView(APIView):
    def get(self, request, *args, **kwargs):
        # return APIResponse(name="shazi",password='123123132',token='asdas.da.dasd')
        # return APIResponse(results=[{"user":'132'},{"hobby":['music','running']}])
        return APIResponse(headers={"hobby":['music','running']})

  • 在HomeView.vue

<template>
  <div class="home">
    <h1>首页</h1>
    <!-- 在这里你可以添加一些内容来显示获取到的数据 -->
    <div v-if="dataFromServer">
      <!-- 使用 dataFromServer 的数据来渲染内容 -->
      <!-- 假设返回的数据是一个对象,并且你想显示其某个属性,例如 message -->
      <p>{{ dataFromServer.message }}</p>
    </div>
  </div>
</template>

<script setup>
import { reactive, onMounted } from 'vue';
import axios from 'axios';

// 使用 reactive 来创建响应式的数据对象
const res = reactive({
  message: ''
});

// 在 onMounted 生命周期钩子中发送请求
onMounted(async () => {
  try {
    const response = await axios.get('http://127.0.0.1:8000/user/option/', {
      headers: {
        // token: 'asd.fas.sadas' // 在请求头中添加自定义的 token
      }
    });
    res.message = response.data.message;
    // 这里可以处理响应的其他数据
    console.log(response);

  } catch (error) {
    console.error('Error fetching data:', error);
    // 在这里你可以选择以某种方式通知用户或处理错误
  }
});
</script>

<style scoped>
/* 你的样式代码 */
</style>

image-20240511172929754

  • 解决方法

from rest_framework.views import APIView
from lufy.utils.utils_response import APIResponse 
class CoreView(APIView):
    def get(self, request, *args, **kwargs):

        # # return APIResponse(headers={"hobby":['music','running']})
        # No 'Access-Control-Allow-Origin' header is present on the requested resource.
        return APIResponse(headers={"Access-Control-Allow-Origin": '*'})

image-20240511175030361

  • Access-Control-Allow-Headers

  • 用于告知浏览器在跨域请求中,所允许的请求头字段

  • urls.py

from django.urls import path
from . import views
from .views import LoggerView, ExceptionView,ResponseView,CoreView,core_view

urlpatterns = [
    # 日志
    path('logg/', LoggerView.as_view(), name='home'),
    # 异常
    path('except/', ExceptionView.as_view()),
    # 响应方法
    path('ponse/', ResponseView.as_view()),
    # 跨域
    path('core/', CoreView.as_view()),

    path('option/', core_view),

]
  • views.py

from rest_framework.views import APIView
from lufy.utils.utils_response import APIResponse 

def core_view(request):
    res = HttpResponse("ok")
    res['Access-Control-Allow-Origin'] = '*'
    if request.method =='OPTIONS':
        res['Access-Control-Allow-Headers'] = '*'
    return res

image-20240511191016929

  • 我现在要使用别的请求方法比如put、delete

<script setup>
import { reactive, onMounted } from 'vue';
import axios from 'axios';

// 使用 reactive 来创建响应式的数据对象
const res = reactive({
  message: ''
});

// 在 onMounted 生命周期钩子中发送请求
onMounted(async () => {
  try {
    const response = await axios.put('http://127.0.0.1:8000/user/option/', {
      headers: {
        token: 'asd.fas.sadas' // 在请求头中添加自定义的 token
      }
    });
    res.message = response.data.message;
    // 这里可以处理响应的其他数据
    console.log(response);

  } catch (error) {
    console.error('Error fetching data:', error);
    // 在这里你可以选择以某种方式通知用户或处理错误
  }
});
</script>

image-20240511191419095

  • 我们只需要添加Access-Control-Allow-Methods

  • res['Access-Control-Allow-Headers'] = '*'
    
def core_view(request):
    res = HttpResponse("ok")
    res['Access-Control-Allow-Origin'] = '*'
    if request.method =='OPTIONS':
        res['Access-Control-Allow-Headers'] = '*'
        res['Access-Control-Allow-Methods'] = '*'
    return res
# 注意注释跨域403
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

image-20240511192131238

image-20240511192156561

​ 非简单请求(non-simple requests)在CORS(跨源资源共享)中,指的是不满足简单请求条件的请求。简单请求和非简单请求的区分主要是基于HTTP请求的一些特性,而不仅仅是基于发送了几次请求。

简单请求需要满足以下条件:

  1. 请求方法只能是以下几种之一:HEAD、GET、POST。
  2. HTTP头信息不超出以下几种字段:
    • Accept
    • Accept-Language
    • Content-Language
    • Last-Event-ID
    • Content-Type:只限于三个值 application/x-www-form-urlencodedmultipart/form-datatext/plain

​ 如果HTTP请求不满足以上条件,那么它就是一个非简单请求。

​ 非简单请求在浏览器发送真正的请求之前,会首先发送一个预检请求(preflight request),请求方法是OPTIONS。预检请求会询问服务器是否允许该跨域请求。服务器响应预检请求时,需要包含一些CORS相关的响应头信息,比如 Access-Control-Allow-OriginAccess-Control-Allow-MethodsAccess-Control-Allow-Headers 等,来告知浏览器该跨域请求是否被允许。

​ 所以,非简单请求并不是看你发送了几次请求,而是看请求的HTTP方法、头信息等是否满足简单请求的条件。如果不满足,浏览器就会发送预检请求,这增加了一次额外的HTTP请求。

【 2 】自定义中间件

  • views.py

from rest_framework.views import APIView
from lufy.utils.utils_response import APIResponse 
def core_view(request):
    res = HttpResponse("ok")

    return res
  • urls.py

from django.urls import path
from . import views
from .views import core_view

urlpatterns = [
    # option
    path('option/', core_view),

]
  • 在utils/utils.
## 中间件###
from django.utils.deprecation import MiddlewareMixin
class CorsMiddleWare(MiddlewareMixin):
    def process_response(self,request,response):
        if request.method=="OPTIONS":
            #可以加*
            response["Access-Control-Allow-Headers"]="*"
            response['Access-Control-Allow-Methods'] = '*'
        response["Access-Control-Allow-Origin"] = "*"
        return response

  • 配置文件新的dev.py

MIDDLEWARE = [

    'utils.utils_middleware.CorsMiddleWare',
]
<template>
  <div class="home">
    <h1>首页</h1>
    <!-- 在这里你可以添加一些内容来显示获取到的数据 -->

      <!-- 使用 dataFromServer 的数据来渲染内容 -->
      <!-- 假设返回的数据是一个对象,并且你想显示其某个属性,例如 message -->
      <p>{{ res.message }}</p>
    </div>

</template>

<script setup>
import { reactive, onMounted } from 'vue';
import axios from 'axios';

// 使用 reactive 来创建响应式的数据对象
const res = reactive({
  message: ''
});

// 在 onMounted 生命周期钩子中发送请求
onMounted(async () => {
  try {
    const response = await axios.put('http://127.0.0.1:8000/user/option/', {
      headers: {
        token: 'asd.fas.sadas' // 在请求头中添加自定义的 token
      }
    });
    res.message = response.data.message;
    // 这里可以处理响应的其他数据
    console.log(response);

  } catch (error) {
    console.error('Error fetching data:', error);
    // 在这里你可以选择以某种方式通知用户或处理错误
  }
});
</script>

<style scoped>
/* 你的样式代码 */
</style>

image-20240511193557916

【 3 】第三方app解决

# 1、使用pip安装
pip install django-cors-headers

# 2、添加到setting的app中
INSTALLED_APPS = (
	...
	'corsheaders',
	...
)
# 3、添加中间件
MIDDLEWARE = [  
	...
	'corsheaders.middleware.CorsMiddleware',
	...
]
# 4、setting下面添加下面的配置
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_METHODS = (
	'DELETE',
	'GET',
	'OPTIONS',
	'PATCH',
	'POST',
	'PUT',
	'VIEW',
)

CORS_ALLOW_HEADERS = (
	'XMLHttpRequest',
	'X_FILENAME',
	'accept-encoding',
	'authorization',
	'content-type',
	'dnt',
	'origin',
	'user-agent',
	'x-csrftoken',
	'x-requested-with',
	'Pragma',
	'token',
)


### 中间件源码分析
if conf.CORS_ALLOW_ALL_ORIGINS and not conf.CORS_ALLOW_CREDENTIALS:
    response[ACCESS_CONTROL_ALLOW_ORIGIN] = "*"
if request.method == "OPTIONS":
            response[ACCESS_CONTROL_ALLOW_HEADERS] = ", ".join(conf.CORS_ALLOW_HEADERS)
            response[ACCESS_CONTROL_ALLOW_METHODS] = ", ".join(conf.CORS_ALLOW_METHODS)
  • 1、使用pip安装

    # pip install django-cors-headers
    

    image-20240511193807957

  • 2、添加到setting的app中

INSTALLED_APPS = (
  	...
  	'corsheaders',
  	...
  )

  • 3、添加中间件

    MIDDLEWARE = [  
    	...
    	'corsheaders.middleware.CorsMiddleware',
    	...
    ]
    
  • 4、setting下面添加下面的配置(放在新建的common_settings)

    CORS_ORIGIN_ALLOW_ALL = True
    CORS_ALLOW_METHODS = (
    	'DELETE',
    	'GET',
    	'OPTIONS',
    	'PATCH',
    	'POST',
    	'PUT',
    	'VIEW',
    )
    
    CORS_ALLOW_HEADERS = (
    	'XMLHttpRequest',
    	'X_FILENAME',
    	'accept-encoding',
    	'authorization',
    	'content-type',
    	'dnt',
    	'origin',
    	'user-agent',
    	'x-csrftoken',
    	'x-requested-with',
    	'Pragma',
    	'token',
    )
    

    image-20240511194116226

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1933676.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Re:从零开始的C++世界——类和对象(下)

文章目录 前言1.再谈构造函数&#x1f34e;构造函数体赋值&#x1f34e;初始化列表&#x1f34e;特性&#x1f34c;特性一&#x1f34c;特性二&#x1f34c;特性三&#x1f34c;特性四&#x1f34c;特性五 &#x1f34e;explicit 关键字 2.static成员&#x1f34e;概念&#x1…

node.js动漫论坛-计算机毕业设计源码09947

摘 要 随着移动互联网的飞速发展&#xff0c;智能手机和移动互联网已经成为人们日常生活中不可或缺的一部分。在这样的背景下&#xff0c;微信小程序应运而生&#xff0c;凭借其无需下载安装、即用即走的特点&#xff0c;迅速成为连接用户与服务的桥梁。动漫作为一种深受年轻人…

《0基础》学习Python——第十六讲 __文件读写

<文件读写> 一、什么是文件读写 文件读写是指在Python程序中对文件进行读取和写入操作。通过文件读写&#xff0c;可以读取文件中的数据&#xff0c;或者向文件中写入数据。 Python提供了多种文件读写的方式&#xff0c;其中最常用的方式是使用open()函数打开一个文件&a…

ssrf复习(及ctfshow351-360)

1. SSRF 概述 服务器会根据用户提交的URL发送一个HTTP请求。使用用户指定的URL&#xff0c;Web应用可以获取图片或者文件资源等。典型的例子是百度识图功能。 如果没有对用户提交URL和远端服务器所返回的信息做合适的验证或过滤&#xff0c;就有可能存在“请求伪造"的缺陷…

huawei USG6001v1学习---信息安全概念

目录 1.什么是分布式&#xff1f; 2.什么是云计算&#xff1f; 3.APT攻击 4.安全风险能见度不足 5.常见的一些攻击 6.交换机转发原理&#xff1f; 7.各层攻击类型 7.1链路层&#xff1a; 7.2网络层&#xff1a; 7.3传输层&#xff1a; 7.4应用层&#xff1a; 1.什么…

mybatis plus json 格式转换踩坑记录

项目中有个字段存的是json数据。 我对应的实体类用的 fastjson2 中的 JsonObject 对象。 实体类&#xff1a; Data Accessors(chain true) TableName(value "plugin_template", autoResultMap true) public class PluginTemplateDo {TableId(type IdType.AUTO)p…

Mybatis<collection>实现一对多

时隔多年又用到这样的查询方式了,提前声明一下分页最后返回的数据会小于每页条数&#xff0c;废话不多说直接上代码&#xff01; Data public class PbcUserTargetTaskPageVO {ApiModelProperty("个人绩效指标id")private Long id;ApiModelProperty("月份"…

Modbus通讯接口选择分析

Modbus通讯接口选择分析 Modbus通讯接口的选择涉及到多个方面的考量&#xff0c;包括但不限于通讯距离、数据传输速率、成本、设备兼容性以及应用场景等。下面将从这些角度出发&#xff0c;对Modbus通讯接口的选择进行详细的分析。 Ip67防水面板法兰插座 通讯距离 Modbus通讯…

VLAN 划分案例详解

vlan 的应用在网络项目中是非常广泛的&#xff0c;基本上大部分的项目都需要划分 vlan&#xff0c;这里从基础的 vlan 的知识开始&#xff0c;了解 vlan 的划分原理。 为什么需要 vlan&#xff1a; 1、什么是 VLAN&#xff1f; VLAN&#xff08;Virtual LAN&#xff09;&…

【面试题】Redo log和Undo log

Redo log 介绍Redo log之前我们需要了解一下&#xff0c;mysql数据操作的流程&#xff1a; 上述就是数据操作的流程图&#xff0c;可以发现sql语句并不是直接操作的磁盘而是通过操作内存&#xff0c;然后进行内存到磁盘的一个同步。这里我们必须要了解一些区域&#xff1a; 缓…

推荐一款使用Java EE技术栈的企业应用定制化开发平台(带源码)

前言 在数字化转型的浪潮中&#xff0c;企业面临着多样化的信息系统建设需求。现有的软件系统往往存在定制化程度低、开发周期长、成-本高等问题。此外&#xff0c;随着企业规模的扩大和业务的复杂化&#xff0c;传统的软件系统难以满足灵活多变的业务需求。 为了解决这些痛点…

【前端7*】表格-表单2(弹窗在子组件)父子组件调用 vue element-ui

vue element-ui 中表单弹框的使用 写在最前面一、子组件 HelloWorld.vue1. 弹窗部分、将 visible 传值给父组件2.表单的 ruleForm 校验方法3.表单确认方法4. 提交确认方法&#xff1a;handleSummit5.表单渲染 二、父组件 HomeView.vue1.新增按钮、查看和编辑2.引用子组件弹窗3.…

【Linux网络】select{理解认识select/select与多线程多进程/认识select函数/使用select开发并发echo服务器}

文章目录 0.理解/认识回顾回调函数select/pollread与直接使用 read 的效率差异 1.认识selectselect/多线程&#xff08;Multi-threading&#xff09;/多进程&#xff08;Multi-processing&#xff09;select函数socket就绪条件select的特点总结 2.select下echo服务器封装套接字…

花开半夏,我决意仿一款答题小程序

不是清凉罢挥扇&#xff0c;自缘手倦歇些时。 ——杨万里&#xff08;宋&#xff09; 走过春的绚烂&#xff0c;路过初夏的清凉&#xff0c;我们迎来了炎炎夏日。蛙声阵阵&#xff0c;蝉鸣声声&#xff0c;稻花如白练&#xff0c;荷花别样红。 花开半夏&#xff0c;我决意仿一款…

C# 各版本语法新功能汇总

C# 8.0 以后 官网 C# 7.3 》》in C# 7.2 》》 命名参数、具名参数 》》》 条件 ref 表达式 C# 7.1 》》 default 运算符 default 在C#7.1中得到了改进&#xff0c;不再需要default&#xff08;T&#xff09;了 //变量赋值C#7.0 var s "字符串"; s default(s…

【常见开源库的二次开发】基于openssl的加密与解密——MD5算法源码解析(六)

一、MD5算法分析 &#xff1a; 1.1 关于MD5 “消息摘要”是指MD5&#xff08;Message Digest Algorithm 5&#xff09;算法。MD5是一种广泛使用的密码散列函数&#xff0c;它可以生成一个128位&#xff08;16字节&#xff09;的散列值。 RFC 1321: MD5由Ronald Rivest在1992…

某大型企业产品研发管理体系构建指南解决方案

获取完整PPT见下图 更多有关华为研发管理/IPD、MBSE、PLM、ERP、MES、数据治理、数字样机等方面免费解决方案、资料获取&#xff0c;请见下图

MySQL学习记录 —— 이십사 MySQL连接层和服务层

文章目录 1、整体架构2、连接层1、网络端口和连接管理线程2、客户端连接线程管理3、连接量管理 3、服务层1、服务管理和公共组件2、NoSQL接口与SQL接口以及Parser语法分析器3、优化器和缓存 4、SQL语句执行流程 1、整体架构 MySQL8.0服务器是由连接池、服务管理工具和公共组件…

BIOMOD2 物种分布模拟教程

原文链接&#xff1a;BIOMOD2 物种分布模拟教程https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247609373&idx5&sn492e7597314a5f9e358c35e4780b275f&chksmfa826dfacdf5e4ecf8ac06bdeba5469b31650bdbefbc8fb88b79c0f332714c453a4cc058d29f&token155…

Linux系统部署MySQL数据库

1.Linux插入光盘&#xff0c;使用df-h获取光盘信息&#xff0c;默认/dev/sr0文件为光盘文件 使用命令 mount -o ro /dev/sr0 /media进行手动挂载 mount -o ro /dev/sr0 /media 2.进入cd /etc/yum.repos.d目录 编辑配置yum库&#xff0c;编辑vim yum.repos [BaseOS] nameba…