Python 框架学习 Django篇 (五) Session与Token认证

news2024/11/17 0:03:48

我们前面经过数据库的学习已经基本了解了怎么接受前端发过来的请求,并处理后返回数据实现了一个基本的登录登出效果,但是存在一个问题,我们是将所有的请求都直接处理了,并没有去检查是否为已经登录的管理员发送的,如果是这样的话客户端可以不选择登录直接去访问主页文件,那么登录就毫无意义了。 所以我们要在处理前端请求前先去判断这个请求的合法性,通常的两种方案就是session 和token

一、session方案

1、session原理

session 表示会话的意思,Django在服务端在数据库中保存一张session表

这个表中记录了用户登录的信息,具体的信息各个系统都略有不同,大致都会有id、姓名、登录名称之类的,在下图中我们可以看到存储着session_key(会话ID) 、session_data (会话数据)可以发现sessionid 通常就是 一串字符串 用来标记一个session的。 而session对应的数据在这里是加密的,通过这张表,服务端 可以根据 session号(通常叫session ID) 查到 session 的信息数据。

 每当用户成功登录之后,服务端都会往数据库表session中记录一条数据,也就是创建一个新的会话id写入数据表,同时也 放入一些 该session对应的数据到 记录的数据字段中,比如登录用户 的 信息。然后在该登录请求的HTTP响应消息中, 的头字段 Set-Cookie 里填入 sessionid 数据

添加输出响应头

vi Django_demo/mgr/sign_in_out.py

import  requests,pprint

payload = {
    'username': 'root',
    'password': '12345678'
}

response = requests.post('http://127.0.0.1:8000/api/mgr/signin',data=payload)

pprint.pprint(response.json())

#输出相应头
for header, value in response.headers.items():
    print(f'{header}: {value}')

返回

{'ret': 0}
Date: Fri, 20 Oct 2023 05:58:54 GMT
Server: WSGIServer/0.2 CPython/3.9.13
Content-Type: application/json
Content-Length: 10
Vary: Cookie
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
Cross-Origin-Opener-Policy: same-origin
Set-Cookie: sessionid=otfwixmjgfngfc45n8k6efobiff4f3xs; 
expires=Fri, 03 Nov 2023 05:58:53 GMT; HttpOnly; Max-Age=1209600; Path=/; SameSite=Lax


#这一行
Set-Cookie: sessionid=otfwixmjgfngfc45n8k6efobiff4f3xs; 

根据http协议, 这个Set-Cookie字段的意思就是 要求前端将其中的数据存入 cookie中。 并且随后访问该服务端的时候, 在HTTP请求消息中必须带上 这些 cookie数据 

cookie 通常就是存储在客户端浏览器的一些数据。 服务端可以通过http响应消息 要求 浏览器存储 一些数据。以后每次访问同一个网站服务, 必须在HTTP请求中再带上这些cookie里面的数据。

cookie数据组成如下

sessionid=6qu1cuk8cxvtf4w9rjxeppexh2izy0hh
username=byhy
favorite=phone_laptop_watch

 该用户的后续操作只要出发http请求, 都会在请求头的Cookie字段添加上面说的sessionID,服务端接受到请求后,只需要到session表中查看是否有该sessionID对应的记录,这样就可以判断这个请求前面是已经登录过,如果不是就可以拒绝服务,重定向http请求到登录页面让用户登录

2、添加主页请求限制

在一开始的登录函数中我们调用了一个函数request.session['usertype'] = 'mgr'

 这行代码的作用 就是在登录认证后,将 用户类型保存到session数据中, 也就是存入前面数据库的那张图的 会话数据记录中,Django 框架 会自动在 HTTP 响应消息头中 加入 类似刚才说的sessionid cookie

Set-Cookie: sessionid=otfwixmjgfngfc45n8k6efobiff4f3xs; 

所以我们处理开通的/api/mgr 需要验证请求的cookie里面是否有sessionid,并且检查session表,看看是否存在session_key为该sessionid 的一条记录,该记录的数据字典里面是否 包含了 usertype 为 mgr 的 数据,我们可以把前面数据库增删改查视为我们的主页,只需要从主页函数调用之前去做下检查即可

vi Django_demo/mgr/k8s.py

def dispatcher(request):  # 将请求参数统一放入request 的 params 属性中,方便后续处理

    # 根据session判断用户是否是登录的管理员用户
    if 'usertype' not in request.session:
        return JsonResponse({
            'ret': 302,
            'msg': '未登录',
            'redirect': '/mgr/sign.html'},
            status=302)

    if request.session['usertype'] != 'mgr' :
        return JsonResponse({
            'ret': 302,
            'msg': '用户非mgr类型',
            'redirect': '/mgr/sign.html'} ,
            status=302)


...

3、测试访问

http://127.0.0.1:8000/api/mgr/customers/?action=list_customer

 可以看到,尝试直接访问后端信息时因为找不到登录时携带的会话id则不运行登录

4、修改测试方法

我们修改一下请求方法,先发送登录请求然后将相应头中的Set-Cookie取出,在发起访问时在请求头中携带获取到的Cookie去请求就能正常访问了

vi main.py

import  requests,pprint

payload = {
    'username': 'root',
    'password': '12345678'
}
#发送登录请求
response = requests.post('http://127.0.0.1:8000/api/mgr/signin',data=payload)


#拿到请求请求响应头中的值
set_cookie = response.headers.get('Set-Cookie')
if set_cookie:
    # 将Set-Cookie字段的值添加到请求头中
    headers = {'Cookie': set_cookie}
    # 发送带有Cookie的新请求
    response = requests.get('http://127.0.0.1:8000/api/mgr/customers/?action=list_customer',headers=headers)
    pprint.pprint(response.json())

返回

{'ret': 0,
 'retlist': [{'ClusterName': 'acp-r1-1',
              'NodeSum': '100',
              'PrometheusAddress': '192.168.1.1',
              'id': 1},
             {'ClusterName': '123123',
              'NodeSum': '123123',
              'PrometheusAddress': '123123',
              'id': 2},
             {'ClusterName': 'gfs-r3-1',
              'NodeSum': '5000',
              'PrometheusAddress': '192.168.1.21',
              'id': 3}]}

二、Token方案

1、session 缺点

1、性能问题   #验证请求是根据sessionid 到数据库中查找session表的
             #而数据库操作是服务端常见的性能瓶颈,尤其是当用户量比较大的时候

2、扩展性问题  #当系统用户特别多的时候,后端处理请求的服务端通常是部署在多个节点上
              #但是多个节点都要访问session表,这样就要求数据库服务能够被多个节点访问
              #不方便切分数据库以提高性能。

token 简单来说,就是包含了数据信息和校验信息的数据包 ,Session 机制是把 数据信息(比如session表)放到 服务端,服务端数据是客户无法篡改的,从而保证验证的 可靠性,而 token机制 数据信息 直接传给 客户端,客户每次请求再携带过来给服务端。服务端无需查找数据库,直接根据token里面的数据信息进行校验

但是上面的方法存在一个问题,假设我是普通用户,那天我获取到了一个vip用户的token,拿是不是我就能访问vip用户的权限了,为了防止

2、token机制说明

1、服务端先创建了一个密钥文件(secret key)

2、用户登录成功后,服务端会将"用户的信息数据"和"密钥"一起进行一个哈希计算从而得到一个哈希值

   首先为了哈希算法保证一致性,只能根据同样的数据源获取,如果有人修改了用户信息成其他人的
   除非他也拿到了密钥, 不然他即使再用哈希算法计算也不会得到我们认证的token值, 所以这个哈希值就方便我们用来做数据校验

   当我们拿到了这个独一无二的哈希值后,将哈希值和用户数据再做成一个字符串
   这个字符串也就被称之为token,token里面包含了用户数据和数据校验的哈希值
   服务端接受到请求后返回token值,通常来说token是放在http响应头部中的, 具体那个头部字段没有规定,可以自定义  



3、用户的后续操作如果除非http api请求则会在请求消息中带上token值

   服务端接收到请求后,会根据数据信息和密钥使用哈希再次生成哈希值,如果用户修改了数据
   因为不知道密钥没有办法得到正确的新的哈希值,那么服务端根据篡改后的数据和密钥得到的新的哈希值一定不同就知道数据被修改了

   如果客户端没有修改数据,服务端根据原来的数据加上密钥得到的哈希值
   与保存在otken中的哈希值一对比,校验通过后就知道没有被修改,可以放心使用token中的用户数据了

三、实现token认证

1、安装库

pip install djangorestframework==3.14.0
pip install djangorestframework-simplejwt 

 2、加载库配置

vi Django_demo/Django_demo/settings.py

INSTALLED_APPS = [
    'simpleui',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'paas',
    'mgr',

    #添加下面的配置
    'rest_framework',
    'rest_framework.authtoken',
    'rest_framework_simplejwt.token_blacklist',
]

3、添加全局配置

vi Django_demo/Django_demo/settings.py

#找个空地方直接贴上,其中包含了认证方式和Token的过期时间等
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.TokenAuthentication',  # 使用Token进行身份验证
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',  # 需要进行身份验证的默认权限类
    ],
    'DEFAULT_THROTTLE_RATES': {
        'user': '100/day',  # 每个用户每天最多可以进行100次请求
        'anon': '10/day'  # 匿名用户每天最多可以进行10次请求
    },
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',  # 默认使用JSON渲染器来渲染响应
    ],
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework.parsers.JSONParser',  # 默认使用JSON解析器来解析请求数据
    ],
    'DEFAULT_METADATA_CLASS':
        'rest_framework.metadata.SimpleMetadata',  # 默认使用简单元数据类
    'DEFAULT_VERSIONING_CLASS':
        'rest_framework.versioning.URLPathVersioning',  # 使用URL路径版本控制
    'DEFAULT_FILTER_BACKENDS': [
        'django_filters.rest_framework.DjangoFilterBackend'  # 默认使用Django Filter后端来进行过滤
    ],
    'DEFAULT_PAGINATION_CLASS':
        'rest_framework.pagination.PageNumberPagination',  # 默认的分页类为PageNumberPagination
    'PAGE_SIZE': 10,  # 默认的每页返回的对象数量为10
    'DEFAULT_THROTTLE_CLASSES': [
        'rest_framework.throttling.AnonRateThrottle',  # 默认使用匿名速率限制类
        'rest_framework.throttling.UserRateThrottle'  # 默认使用用户速率限制类
    ],
    'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',  # 默认使用AutoSchema来生成API文档
    'DEFAULT_CONTENT_NEGOTIATION_CLASS': 'rest_framework.negotiation.DefaultContentNegotiation',  # 默认使用DefaultContentNegotiation进行内容协商
    'COERCE_DECIMAL_TO_STRING': False,  # 数字类型是否强制转换为字符串
    'DATETIME_FORMAT': '%Y-%m-%d %H:%M:%S',  # 默认的日期时间格式
    'DATETIME_INPUT_FORMATS': [
        '%Y-%m-%d %H:%M:%S',
        '%Y-%m-%d %H:%M',
        '%Y-%m-%d',
        '%Y%m%dT%H%M%S%fz'
    ],  # 接受的日期时间输入格式的列表
    'UNICODE_JSON': False,  # 是否使用Unicode编码的JSON
}

我们设置了TokenAuthentication作为默认的认证方式,同时设置了IsAuthenticated权限,表示只有已认证用户才能访问

4、同步库数据库操作

python manage.py makemigrations
python manage.py migrate

5、注释前面session认证

我们先将之前写的session判断给注释掉

vi Django_demo/mgr/k8s.py

    # 根据session判断用户是否是登录的管理员用户
    if 'usertype' not in request.session:
        return JsonResponse({
            'ret': 302,
            'msg': '未登录',
            'redirect': '/mgr/sign.html'},
            status=302)

    if request.session['usertype'] != 'mgr' :
        return JsonResponse({
            'ret': 302,
            'msg': '用户非mgr类型',
            'redirect': '/mgr/sign.html'} ,
            status=302)

此时我们访问查询应该就可以直接访问通了

http://127.0.0.1:8000/api/mgr/customers/?action=list_customer

 6、开启主页函数token验证

vi Django_demo/mgr/k8s.py

#导入模块
from rest_framework.authentication import TokenAuthentication  # 导入TokenAuthentication类,用于基于令牌进行身份验证
from rest_framework.permissions import IsAuthenticated  # 导入IsAuthenticated类,用于检查用户是否已通过身份验证的权限
from rest_framework.decorators import api_view, permission_classes, authentication_classes  # 导入装饰器函数,用于设置视图函数的身份验证和权限控制



#添加装饰器
@api_view(['GET'])
@authentication_classes([TokenAuthentication])  # 使用TokenAuthentication类进行身份验证
@permission_classes([IsAuthenticated])  # 要求用户已通过身份验证
def dispatcher(request): 
    ...
http://127.0.0.1:8000/api/mgr/customers/?action=list_customer

 我们需要让应用登录成功后获取到一个token值,这里的token我们通过直接取用户

(下面是说明代码不执行)

from rest_framework.authtoken.models import Token  # 导入 Token 模型,用于创建和管理用户的 Token
from django.contrib.auth.models import User  # 导入 User 模型,用于获取用户对象

# 获取用户
user = User.objects.get(username='root')  # 根据用户名获取用户对象

# 创建 Token
token, created = Token.objects.get_or_create(user=user)  # 创建或获取与用户关联的 Token

7、登录函数添加token获取

在登录函数,登录成功之后添加一个获取登录用户token的值,并跟随相应头返回token

Django_demo/mgr/sign_in_out.py

def signin( request):
    userName = request.POST.get('username')
    passWord = request.POST.get('password')

    user = authenticate(username=userName, password=passWord)

    if user is not None:
        if user.is_active:
            if user.is_superuser:
                login(request, user)
                request.session['usertype'] = 'mgr'




                #添加返回用户的token
                from rest_framework.authtoken.models import Token
                from django.contrib.auth.models import User
                user = User.objects.get(username=userName)

                # 创建或获取 Token
                token, created = Token.objects.get_or_create(user=user)
                return JsonResponse({'token': str(token), 'ret': 0})



            else:
                return JsonResponse({'ret': 1, 'msg': '请使用管理员账户登录'})
        else:
            return JsonResponse({'ret': 0, 'msg': '用户已经被禁用'})

    # 否则就是用户名、密码有误
    else:
        return JsonResponse({'ret': 1, 'msg': '用户名或者密码错误'})

8、测试检查是否返回token值

vi main.py

import  requests,pprint

payload = {
    'username': 'root',
    'password': '12345678'
}
#发送登录请求
response = requests.post('http://127.0.0.1:8000/api/mgr/signin',data=payload)
print(response.headers.get('Authorization'))

返回

Token 1568e26d12af8a5a6489603763e662cf0c65c73a

9、携带token值请求主页

vi main.py

import  requests,pprint

payload = {
    'username': 'root',
    'password': '12345678'
}
#发送登录请求
response = requests.post('http://127.0.0.1:8000/api/mgr/signin',data=payload)
token = response.headers.get('Authorization')


#携带token请求
if token:
    # 将Set-Cookie字段的值添加到请求头中
    headers = {'Authorization': f'{token}'}
    response = requests.get('http://127.0.0.1:8000/api/mgr/customers/?action=list_customer',headers=headers)
    pprint.pprint(response.json())

返回

{'ret': 0,
 'retlist': [{'ClusterName': 'acp-r1-1',
              'NodeSum': '100',
              'PrometheusAddress': '192.168.1.1',
              'id': 1},
             {'ClusterName': '123123',
              'NodeSum': '123123',
              'PrometheusAddress': '123123',
              'id': 2},
             {'ClusterName': 'gfs-r3-1',
              'NodeSum': '5000',
              'PrometheusAddress': '192.168.1.21',
              'id': 3}]}

10、数据库内的token查询

牌(Token)在Django Rest Framework中是使用默认的Authentication模块提供的,它默认存储在数据库中,并且没有过期时间。这意味着一旦生成并分配给用户,Token将一直有效,直到被明确删除。

存储Token的数据库表是authtoken_token,在数据库中的位置取决于你的Django项目的数据库配置。

默认情况下,Token会与用户相关联,并且将存储在Token模型的user字段中。每个用户可以有多个Token,因此可以在这个模型上执行标准的查询操作

如果你希望对Token设置过期时间,或者有更高级的需求,你可以考虑使用第三方库,如django-rest-framework-simplejwt。这个库提供了JWT(JSON Web Token)认证,可以根据特定的配置设置Token的过期时间和其他功能。

 

四、session和token的区别详解

1、存储位置

Token:Token通常存储在服务器端的数据库中,或者可以存储在客户端的cookie或本地存储中。每次发起请求时,Token将通过请求头或请求参数进行传递。

Session:Session通常存储在服务器端的数据库或缓存中。服务器将为每个会话分配一个唯一的Session ID,并将Session ID存储在客户端的cookie中。客户端在发送请求时会自动携带Session ID。

2、无状态性

Token    Token是无状态的,服务器不需要在后端存储任何关于用户会话的状态信息。
         每个请求都包含所有必要的信息(通常是在Token本身中)来进行身份验证和授权。

Session:Session是有状态的,服务器需要在后端存储有关用户会话的状态信息。客户端的每个请求都需要携带Session ID,服务器根据Session ID检索并验证对应的会话状态。

3、扩展性和跨域支持

Token  由于Token是无状态的,因此易于扩展和支持跨域请求。
        服务器不需要存储每个用户的会话状态,因此可以更好地支持负载均衡和分布式系统。

Session  由于Session是有状态的,需要在服务器端存储状态信息,
         因此在处理大量并发请求或跨域请求时可能存在一些挑战。

4、过期和失效机制

Token   Token可以通过设置过期时间来自动失效,或者可以通过撤销Token的方式来手动使其失效。
        客户端需要负责在失效前获取新的Token。

Session   Session可以通过设置过期时间来自动失效,但服务器也可以更主动地管理会话状态
          例如在用户注销或一段时间内无活动后自动销毁会话。

总结

Token适用于无状态、扩展性要求高、移动应用程序的场景,而Session适用于有状态、需要跟踪用户会话状态的场景

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

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

相关文章

基于ssm网上鲜花店

功能如下图所示 摘要 基于SSM(Spring、Spring MVC、MyBatis)的网上鲜花店,是一款全面电子商务平台,为用户提供了多层次、多功能的鲜花购物体验。该系统的架构结构使得用户可以注册、浏览商品、购物车管理、下单和支付等一系列操作…

智慧园区内涝积水解决方案

在当今园区化快速发展的背景下,智慧园区已经成为园区可持续发展的重要组成部分。然而,智慧园区的规划和运营需要一个综合性的方法,以应对各种挑战,其中之一是积水管理。为了有效地解决这一问题,WITBEE万宾针对智慧园区…

Linux 僵尸进程处理

现象 查看: # 查看僵尸进程 ps -aux |grep Z## ps -aux |grep Z|wc -l 定位僵尸进程 ## ps -A -ostat,ppid,pid,cmd |grep -e ^[Zz] 杀死僵尸进程 使用Kill -HUP 僵尸进程ID来杀死僵尸进程,往往此种情况无法杀死僵尸进程,此时就需要杀死僵尸进程的父进程。 kill -HUP …

051校园短期闲置资源置换平台

大家好✌!我是CZ淡陌。一名专注以理论为基础实战为主的技术博主,将再这里为大家分享优质的实战项目,本人在Java毕业设计领域有多年的经验,陆续会更新更多优质的Java实战项目,希望你能有所收获,少走一些弯路…

【异步爬虫】requests和aiohttp中代理IP的使用

前言 在进行爬虫开发时,我们常常需要使用代理IP来隐藏自己的真实IP地址,以避免被一些网站限制或封禁。requests和aiohttp是两个非常常用的工具,本文将分别介绍如何在它们中使用代理IP,希望可以帮助大家更好地进行异步爬虫开发。 …

1024程序员节特辑 | 解密Spring Cloud Hystrix熔断提高系统的可用性和容错能力

目录 1、Spring Cloud Hystrix 的背景和意义2、Spring Cloud Hystrix 的架构设计3、Spring Cloud Hystrix 的主要组件4、Spring Cloud Hystrix 熔断器的底层原理和整体架构5、Spring Cloud Hystrix 命令6、Spring Cloud Hystrix 熔断器7、Spring Cloud Hystrix参数说明8、Sprin…

点云平面拟合新国标怎么应对?

文章目录 一、应用背景二、算法原理三、代码实现首先我们看一下平面度的概念: 平面度:测量点集合中,在平面上方且距离基准平面最远的点到平面的距离+在平面下方且距离基准平面最远的点到平面的距离。 一、应用背景 在旧标准中,使用最小二乘法去拟合全部点,以拟合平面作为…

Cesium 实战 - 调整饱和度、对比度等参数,加载渲染美化影像底图

Cesium 实战 - 调整饱和度、对比度等参数,加载渲染美化影像底图 渲染美化影像底图核心代码完整代码:在线示例 本文包括渲染美化影像底图核心代码、完整代码以及在线示例。 渲染美化影像底图核心代码 这里放上核心代码: /*** todo 开启美化底…

阿里云oss丨You have no right to access this object because of bucket acl.

错误:You have no right to access this object because of bucket acl. ​ ​ 今天折腾oss的时候遇到这个问题,我以为是我没加白名单,后来想了下应该是使用阿里云OSS上传文件服务时报的错,新建的子用户AccessKey没有配置相应的管…

2023年最佳项目管理软件排行榜揭晓!

根据网络数据调查结果显示,今年有77%的组织将效率列为优先事项,而82%的领导人确认投资于新的项目管理和工作管理方案以提高效能。然而随着对价值的重新关注,选择适合的工程项目管理软件变得比以往任何时候都更加重要。好消息是通过对39个主要…

拿下域控主机

1.装域控环境 是dns环境 域控dns127.0.0.1 二.搭建 加入域 新建域用户 密码和域内主机一样 添加账户和密码 添加到域管理 这个随便 为了后期实验添加上 添加web和远程桌面 域控 用户添加到域 配置dns 攻击 kali 是公网 配置 木马服务器 哈希值 win10 客…

协同过滤推荐算法UserCF、ItemCF

目录 相似度计算基于用户的协同过滤(UserCF)算法评估基于物品的协同过滤(ItemCF)协同过滤算法的权重改进协同过滤算法的问题分析思考学习参考 相似度计算 杰卡德(Jaccard)相似系数 Jaccard 系数是衡量两个…

AMD推出锐龙Threadripper 7000处理器 96核重回HEDT市场

AMD今天正式推出了锐龙Threadripper 7000系列处理器,而且这次不光只有面向工作站的锐龙Threadripper PRO 7000WX系列,还有面向HEDT平台的锐龙Threadripper 7000X系列。 上一代的锐龙Threadripper PRO 5000是去年年初推出的,相隔已经有一年半…

一次说全COLA应用架构

一,为什么需要好的应用架构 上图比较清晰地说明了好的应用架构的作用——去繁为简,化无序为有序。 二,关于COLA的几种定义 1,原版 GitHub - alibaba/COLA: 🥤 COLA: Clean Object-oriented & Layered Architec…

【Linux】文件IO基础知识——上篇,文件描述符是什么??系统缓冲区又是啥??

目录 前文 一, 系统级——文件操作接口 a. open b. close c. write d. read 二,接口理解 那文件描述符——fd是什么呢? 三,文件描述符分配规则 原理 四,重定向——dup2 简易shell——重定向 五&#xff0c…

vue3+ts 使用vue-print-nb 打印功能【完美】

安装 npm i vue3-print-nb -s我的版本 0.1.4 注册 import { createApp } from vue import pinia from ./store import router from ./router import ./assets/css/main.scss import { globalRegister } from /global/register import ant-design-vue/es/message/style/css …

织造业的数字安全守护者:深入了解迅软DSE数据加密

客户简要介绍 某织造企业成立于2004年,工厂位于苏州平望,公司目前拥有先进纺织设备330台套和日本瑞士等前道配套设备,公司占地33亩、具有现代化标准厂房办公楼等3万平米。 某织造企业面料、功能性面料、新材料面料的生产商,公司坚…

UE5 ChaosVehicles载具 实现大漂移 (连载四)

载具设置成前驱模式 前轮摩擦力倍增x5 后轮摩擦力倍增x0.5

Linux 基础操作手记三(内存篇)

Linux 基础操作手记三 释放内存虚拟机彻底无网络测试网速设置虚拟内存交换空间未使用虚拟机设置虚拟内存无法开机问题GParted - 分配内存系统盘扩容自己 释放内存 sync && echo 3 > /proc/sys/vm/drop_caches 虚拟机彻底无网络 还原默认设置,静静的等待…

观测云产品更新 | 优化 SSO 管理、新增监控器类型、优化场景等

本期更新主要分为观测云更新、观测云部署版更新、DataKit 更新、集成更新等内容。详情见官网文档:https://docs.guance.com/release-notes/ 观测云更新 付费计划与账单 计费项【数据转发】统计逻辑变更为 “按照数据转发规则” 统计转发数据量大小。 SSO 管理 …