DRF之JWT认证

news2024/9/30 1:40:21

一、JWT认证

在用户注册或登录后,我们想记录用户的登录状态,或者为用户创建身份认证的凭证。我们不再使用Session认证机制,而使用Json Web Token(本质就是token)认证机制。

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

 

 

 

 1.1 构成和工作原理

 JWT的构成

JWT就是一段字符串,由三段信息构成的,将这三段信息文本用.链接一起就构成了Jwt字符串。就像这样:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
 

 第一部分我们称它为头部(header),第二部分我们称其为载荷(payload, 类似于飞机上承载的物品),第三部分是签证(signature).

1.1.1 header

jwt的头部承载两部分信息:

  • 声明类型,这里是jwt
  • 声明加密的算法 通常直接使用 HMAC SHA256

完整的头部就像下面这样的JSON:

{
  'typ': 'JWT',
  'alg': 'HS256'
}

然后将头部进行base64加密(该加密是可以对称解密的),构成了第一部分.

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

 1.1.2 payload

载荷就是存放有效信息的地方。这个名字像是特指飞机上承载的货品,这些有效信息包含三个部分

  • 标准中注册的声明
  • 公共的声明
  • 私有的声明

标准中注册的声明 (建议但不强制使用) :

  • iss: jwt签发者
  • sub: jwt所面向的用户
  • aud: 接收jwt的一方
  • exp: jwt的过期时间,这个过期时间必须要大于签发时间
  • nbf: 定义在什么时间之前,该jwt都是不可用的.
  • iat: jwt的签发时间
  • jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避时序攻击。

公共的声明 : 公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密.

私有的声明 : 私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。

定义一个payload:

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

然后将其进行base64加密,得到JWT的第二部分。

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9

1.1.3 signature

JWT的第三部分是一个签证信息,这个签证信息由三部分组成:

  • header (base64后的)
  • payload (base64后的)
  • secret

这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分。

// javascript
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);

var signature = HMACSHA256(encodedString, 'secret'); // TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

将这三部分用.连接成一个完整的字符串,构成了最终的jwt:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
 

注意:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。

关于签发和核验JWT,我们可以使用Django REST framework JWT扩展来完成。

1.2 本质原理

jwt认证算法:签发与校验

"""
1)jwt分三段式:头.体.签名 (head.payload.sgin)
2)头和体是可逆加密,让服务器可以反解出user对象;签名是不可逆加密,保证整个token的安全性的
3)头体签名三部分,都是采用json格式的字符串,进行加密,可逆加密一般采用base64算法,不可逆加密一般采用hash(md5)算法
4)头中的内容是基本信息:公司信息、项目组信息、token采用的加密方式信息
{
  "company": "公司信息",
  ...
}
5)体中的内容是关键信息:用户主键、用户名、签发时客户端信息(设备号、地址)、过期时间
{
  "user_id": 1,
 ...
}
6)签名中的内容时安全信息:头的加密结果 + 体的加密结果 + 服务器不对外公开的安全码 进行md5加密
{
 "head": "头的加密字符串",
  "payload": "体的加密字符串",
 "secret_key": "安全码"
}
"""

签发:根据登录请求提交来的 账号 + 密码 + 设备信息 签发 token

"""
1)用基本信息存储json字典,采用base64算法加密得到 头字符串
2)用关键信息存储json字典,采用base64算法加密得到 体字符串
3)用头、体加密字符串再加安全码信息存储json字典,采用hash md5算法加密得到 签名字符串

账号密码就能根据User表得到user对象,形成的三段字符串用 . 拼接成token返回给前台
"""

校验:根据客户端带token的请求 反解出 user 对象

"""
1)将token按 . 拆分为三段字符串,第一段 头加密字符串 一般不需要做任何处理
2)第二段 体加密字符串,要反解出用户主键,通过主键从User表中就能得到登录用户,过期时间和设备信息都是安全信息,确保token没过期,且时同一设备来的
3)再用 第一段 + 第二段 + 服务器安全码 不可逆md5加密,与第三段 签名字符串 进行碰撞校验,通过后才能代表第二段校验得到的user对象就是合法的登录用户
"""

drf项目的jwt认证开发流程(重点)

"""
1)用账号密码访问登录接口,登录接口逻辑中调用 签发token 算法,得到token,返回给客户端,客户端自己存到cookies中

2)校验token的算法应该写在认证类中(在认证类中调用),全局配置给认证组件,所有视图类请求,都会进行认证校验,所以请求带了token,就会反解出user对象,在视图类中用request.user就能访问登录的用户

注:登录接口需要做 认证 + 权限 两个局部禁用
"""

1.2.1 补充base64编码解码

import base64
import json
dic_info={
  "sub": "1234567890",
  "name": "lqz",
  "admin": True
}
byte_info=json.dumps(dic_info).encode('utf-8')
# base64编码
base64_str=base64.b64encode(byte_info)
print(base64_str)
# base64解码
base64_str='eyJzdWIiOiAiMTIzNDU2Nzg5MCIsICJuYW1lIjogImxxeiIsICJhZG1pbiI6IHRydWV9'
str_url = base64.b64decode(base64_str).decode("utf-8")
print(str_url)

二 drf-jwt安装和简单使用

2.1官网

http://getblimp.github.io/django-rest-framework-jwt/

2.2 安装

pip install djangorestframework-jwt

2.3 使用:

# 1 创建超级用户
python3 manage.py createsuperuser
# 2 配置路由urls.py
from django.urls import path
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
    path('login/', obtain_jwt_token),
]
# 3 postman测试
向后端接口发送post请求,携带用户名密码,即可看到生成的token

# 4 setting.py中配置认证使用jwt提供的jsonwebtoken
# 5 postman发送访问请求(必须带jwt空格)

三 实战之使用Django auth的User表自动签发

3.1 配置setting.py

import datetime
JWT_AUTH = {
    # 过期时间1天
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
    # 自定义认证结果:见下方序列化user和自定义response
    # 如果不自定义,返回的格式是固定的,只有token字段
    'JWT_RESPONSE_PAYLOAD_HANDLER': 'users.utils.jwt_response_payload_handler',  
}

3.2 编写序列化类ser.py

from rest_framework import serializers
from users import models
class UserModelSerializers(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = ['username']

3.3 自定义认证返回结果(setting中配置的)

#utils.py
from users.ser import UserModelSerializers
def jwt_response_payload_handler(token, user=None, request=None):
    return {
        'status': 0,
        'msg': 'ok',
        'data': {
            'token': token,
            'user': UserModelSerializers(user).data
        }
    }

3.4 基于drf-jwt的全局认证:

#app_auth.py(自己创建)
from rest_framework.exceptions import AuthenticationFailed
from rest_framework_jwt.authentication import jwt_decode_handler
from rest_framework_jwt.authentication import get_authorization_header,jwt_get_username_from_payload
from rest_framework_jwt.authentication import BaseJSONWebTokenAuthentication

class JSONWebTokenAuthentication(BaseJSONWebTokenAuthentication):
    def authenticate(self, request):
        jwt_value = get_authorization_header(request)

        if not jwt_value:
            raise AuthenticationFailed('Authorization 字段是必须的')
        try:
            payload = jwt_decode_handler(jwt_value)
        except jwt.ExpiredSignature:
            raise AuthenticationFailed('签名过期')
        except jwt.InvalidTokenError:
            raise AuthenticationFailed('非法用户')
        user = self.authenticate_credentials(payload)

        return user, jwt_value

3.5 全局使用

# setting.py
REST_FRAMEWORK = {
    # 认证模块
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'users.app_auth.JSONWebTokenAuthentication',
    ),
}

3.6 局部启用禁用

# 局部禁用
authentication_classes = []
# 局部启用
from user.authentications import JSONWebTokenAuthentication
authentication_classes = [JSONWebTokenAuthentication]
# 实际代码如下view.py
# 自定义Response
class CommonResponse(Response):
    def __init__(self,status,msg,data='',*args,**kwargs):
        dic={'status':status,'msg':msg,'data':data}
        super().__init__(data=dic,*args,**kwargs)
# 测试订单接口
from users.app_auth import JSONWebTokenAuthentication
class OrderView(APIView):
    # authentication_classes = [JSONWebTokenAuthentication]
    authentication_classes = []
    def get(self,request):
        return CommonResponse('100', '成功',{'数据':'测试'})

四 实战之自定义User表,手动签发

4.1 手动签发JWT:

# 可以拥有原生登录基于Model类user对象签发JWT
from rest_framework_jwt.settings import api_settings
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)

4.2 编写登陆视图类

# views.py
from rest_framework_jwt.settings import api_settings
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
from users.models import User
class LoginView(APIView):
    authentication_classes = []
    def post(self,request):
        username=request.data.get('username')
        password=request.data.get('password')
        user=User.objects.filter(username=username,password=password).first()
        if user: # 能查到,登陆成功,手动签发
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)
            return CommonResponse('100','登陆成功',data={'token':token})
        else:
            return CommonResponse('101', '登陆失败')

4.3 编写认证组件

# app_auth.py
from users.models import User
class MyJSONWebTokenAuthentication(BaseAuthentication):
    def authenticate(self, request):
        jwt_value = get_authorization_header(request)

        if not jwt_value:
            raise AuthenticationFailed('Authorization 字段是必须的')
        try:
            payload = jwt_decode_handler(jwt_value)
        except jwt.ExpiredSignature:
            raise AuthenticationFailed('签名过期')
        except jwt.InvalidTokenError:
            raise AuthenticationFailed('非法用户')
        username = jwt_get_username_from_payload(payload)
        print(username)
        user = User.objects.filter(username=username).first()
        print(user)

        return user, jwt_value

4.4 登陆获取token

 4.5编写测试接口

from users.app_auth import JSONWebTokenAuthentication,MyJSONWebTokenAuthentication
class OrderView(APIView):
    # authentication_classes = [JSONWebTokenAuthentication]
    authentication_classes = [MyJSONWebTokenAuthentication]
    def get(self,request):
        print(request.user)
        return CommonResponse('100', '成功',{'数据':'测试'})

4.6 测试

五、源码分析

5.1drf—jwt的签发源码分析

5.1.1 from rest_framework_jwt.views import obtain_jwt_token

obtain_jwt_token就是ObtainJSONWebToken.as_view()---》视图类.as_view()

视图类

class ObtainJSONWebToken(JSONWebTokenAPIView):
    serializer_class = JSONWebTokenSerializer

父类:JSONWebTokenAPIView

class JSONWebTokenAPIView(APIView):
    # 局部禁用掉权限和认证
    permission_classes = ()
    authentication_classes = ()
    def post(self, request, *args, **kwargs):

serializer=JSONWebTokenSerializer(data=request.data)

serializer = self.get_serializer(data=request.data)

调用序列化列的is_valid---》字段自己的校验规则,局部钩子和全局钩子

读JSONWebTokenSerializer的局部或全局钩子

if serializer.is_valid(): # 全局钩子在校验用户,生成token

从序列化类中取出user

user = serializer.object.get('user') or request.user

从序列化类中取出token

token = serializer.object.get('token')

定制返回格式的时候,写的就是这个函数

response_data = jwt_response_payload_handler(token, user, request)
            response = Response(response_data)
            return response

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

JSONWebTokenSerializer的全局钩子

class JSONWebTokenSerializer(Serializer):
    def validate(self, attrs):
        # attrs前端传入的,校验过后的数据 {username:lqz,password:lqz12345}
credentials = {
            'username': attrs.get('usernme'),
            'password': attrs.get('password')
        }

        if all(credentials.values()): # 校验credentials中字典的value值是否都不为空
            # user=authenticate(username=前端传入的,password=前端传入的)
            # auth模块的用户名密码认证函数,可以传入用户名密码,去auth的user表中校验用户是否存在
            # 等同于:User.object.filter(username=username,password=加密后的密码).first()
 user = authenticate(**credentials)
            if user:
                if not user.is_active:
                    msg = _('User account is disabled.')
                    raise serializers.ValidationError(msg)

                payload = jwt_payload_handler(user)

                return {
                    'token': jwt_encode_handler(payload),
                    'user': user
                }
            else:
                msg = _('Unable to log in with provided credentials.')
                raise serializers.ValidationError(msg)
        else:
            msg = _('Must include "{username_field}" and "password".')
            msg = msg.format(username_field=self.username_field)
            raise serializers.ValidationError(msg)

5.2认证源码

from rest_framework_jwt.authentication import JSONWebTokenAuthentication

JSONWebTokenAuthentication

class JSONWebTokenAuthentication(BaseJSONWebTokenAuthentication):
    def get_jwt_value(self, request):
        # auth=['jwt','token串']
        auth = get_authorization_header(request).split()
        auth_header_prefix = api_settings.JWT_AUTH_HEADER_PREFIX.lower()
        if not auth:
            if api_settings.JWT_AUTH_COOKIE:
                return request.COOKIES.get(api_settings.JWT_AUTH_COOKIE)
            return None
        if smart_text(auth[0].lower()) != auth_header_prefix:
            return None
        if len(auth) == 1:
            msg = _('Invalid Authorization header. No credentials provided.')
            raise exceptions.AuthenticationFailed(msg)
        elif len(auth) > 2:
            msg = _('Invalid Authorization header. Credentials string '
                    'should not contain spaces.')
            raise exceptions.AuthenticationFailed(msg)
        return auth[1] # token串

父类中找:BaseJSONWebTokenAuthentication---》authenticate,找到了

class BaseJSONWebTokenAuthentication(BaseAuthentication):
    def authenticate(self, request):
        # 拿到前端传入的token,前端传入的样子是  jwt token串
        jwt_value = self.get_jwt_value(request)
        # 如果前端没传,返回None,request.user中就没有当前登录用户
        # 如果前端没有携带token,也能进入到视图类的方法中执行,控制不住登录用户
        # 所以咱们才加了个权限类,来做控制
        if jwt_value is None:
            return None
        try:
            payload = jwt_decode_handler(jwt_value)
        except jwt.ExpiredSignature:
            msg = _('Signature has expired.')
            raise exceptions.AuthenticationFailed(msg)
        except jwt.DecodeError:
            msg = _('Error decoding signature.')
            raise exceptions.AuthenticationFailed(msg)
        except jwt.InvalidTokenError:
            raise exceptions.AuthenticationFailed()

通过payload拿到当前登录用户

user = self.authenticate_credentials(payload)
        return (user, jwt_value)

 如果用户不携带token,也能认证通过

所以我们必须加个权限类来限制

class IsAuthenticated(BasePermission):
    def has_permission(self, request, view):
        return bool(request.user and request.user.is_authenticated)

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

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

相关文章

给osg::Geometry(自己绘制的几何体)添加纹理(二)

目录 1. 前言 2. 自会集合体贴纹理 2.1. 一张图贴到整个几何体 2.2. 几何体每个面贴不同的图片纹理 3. 说明 1. 前言 前文讲述了如何给osg自带的几何体,如:BOX等,添加纹理,文章参考链接如下: osg给osg::Geometry&…

动态规划专题一(动态规划的基本模型)

先上例题1 1258:【例9.2】数字金字塔 信息学奥赛一本通(C版)在线评测系统 (ssoier.cn) 1258:【例9.2】数字金字塔 时间限制: 1000 ms 内存限制: 65536 KB 提交数: 36341 通过数: 21547 【题目描述】 观察下面的数字…

HotSpot虚拟机OutOfMemoryError异常

目录 一、JVM内存区域 二、堆中对象 1. 对象的创建 2. 对象的内存布局 3. 对象的访问定位 三、OOM异常 1. 堆OOM异常测试 2. 栈SOF异常测试 1):栈容量过小 2):大量本地变量 3. 常量池OOM异常测试 4. 方法区测试 5. 堆外内存测试 四、参考资料…

详解FreeRTOS:嵌入式多任务系统的任务互斥和优先级反转(理论篇—9)

在嵌入式多任务系统中,有些资源必须是独占使用的,多个任务对这样的资源的并发访问将导致错误的发生。一般来说,对需要独占使用的资源必须使用互斥方法将对其的并发访问串行化。 在优先级多任务系统中引入互斥方案,会导致任务优先级反转的问题:假如某时低优先级的任务占有…

Zabbix之2023 Zabbix6.4最新高级特性、优缺点及其实现原理总结

目录 Zabbix高级特性1. 自动发现 Zabbix高级特性2. 分布式监控 Zabbix高级特性3. 高级报警 Zabbix高级特性4. 可视化 Zabbix高级特性5. API Zabbix高级特性6. 高可用性 Zabbix高级特性7. 安全性 Zabbix高级特性8. 无代理监控 SNMP IPMI JMX Zabbix高级特性9. Agent…

【Windows】局域网内远程桌面控制

【Windows】局域网内远程桌面控制 1、背景2、设置登录密码3、启用远程桌面4、远程示例 1、背景 工作中的很多场景需要远程操作,这时候可以借助远程桌面应用程序实现, 比如AnyDesk、向日葵、TeamViewer等。 windows10系统,其操作系统自带了远…

python基础知识(三):比较运算符、布尔运算符和位运算

目录 1. 比较运算符2. 布尔运算符3. 位运算 1. 比较运算符 比较运算符通常为以下6种: (1) 大于">“,比较两个数a、b的大小,比较的结果如果a大于b则为True,否则为False; (2) 大于等于”>“,比较…

【论文阅读笔记】Contrast image correction method

论文小结: 本文是2010年发表出来的一篇文章,提出的方法是一种增强对比度的方法,其基本原理是自适应参数的 ganma 校正。ganma 校正的目标在于同时校正曝光过度和曝光不足区域的图像。   同时,为了防止光晕伪影,使用双…

vue 【git】

文章目录 前言一、git 工作流程二、常用的git命令1.git 初始化2.修改的内容提交到暂存区3.暂存区的内容提交到本地仓库4.创建分支5.切换分支6.展示分支7.删除分支8.合并指定分支到当前分支9.本地仓库的内容提交到远程仓库10.合并分支11.上传本地仓库分支到远程仓库分支 前言 什…

路径规划算法:基于闪电搜索优化的路径规划算法- 附代码

路径规划算法:基于闪电搜索优化的路径规划算法- 附代码 文章目录 路径规划算法:基于闪电搜索优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要:本文主要介绍利用智能优化…

第12届蓝桥杯Scratch国赛真题集锦

程题 第 1 题 问答题 博土江出题 题目说明 编程实现:博土汪出了5道加法选择题,请同学们给出正确选项 具体要求 1).博士汪问:“n m ?”,n (0-9随机数),m (0-9随机数) 2).下方A、B、C、D四个选项,随机一个选项为正确答案&#xff…

通过Python的PyPDF2库合并多个pdf文件

文章目录 前言一、PyPDF2库是什么?二、安装PyPDF2库三、查看PyPDF2库版本四、合并多个pdf文件1.引入库2.定义pdf路径3.获取所有要合并的PDF文件名4.创建一个新的PDF文件5.遍历所有PDF文件名6.打开PDF文件7.创建PDF阅读器对象8.遍历PDF中的每一页,并将它们…

嵌入式c语言-进制转换

10进制转2进制 以10进制的16,18为例子 利用短除法 每次除以2并且记录余数 直到商为1 然后从下往上写出 商余数 10进制转16进制 以55 180 500举例 利用短除法 每次除以16并且记录余数 直到商为1 然后从下往上写出 商余数 商和余数要写成16进制的形式 10进制转8进制 以15为…

(浙大陈越版)数据结构 第三章 树(上) 3.3 二叉树的遍历

目录 3.3.1 遍历(先中后) 二叉树的遍历 先序遍历: 中序遍历 后序遍历 tips: 3.3.2 中序非递归遍历 非递归算法实现的基本思路:使用堆栈 中序遍历的非递归算法具体实现方法为: 3.3.3 层序遍历 难点 解决方法…

经典神经网络(5)GoogLeNet及其在Fashion-MNIST数据集上的应用

经典神经网络(5)GoogLeNet及其在Fashion-MNIST数据集上的应用 1 Inception V1 的简述 Inception 网络是卷积神经网络的一个重要里程碑。在Inception 之前,大部分流行的卷积神经网络仅仅是把卷积层堆叠得越来越多,使得网络越来越深。这使得网络越来越复杂…

计算机组成原理-中央处理器-控制器功能和原理

目录 一、硬布线控制器 二、硬布线控制器的设计(硬件) 2.1分析每个阶段的微操作序列(取址、间址、执行、中断) 2.2选择cpu的控制方式 2.3 安排微操作时序 2.4电路设计 2.4.1列出操作时间表 2.4.2 写出微操作命令的最简表达式 2.4.3画出电路图 *三、微程序控制器基本原理 四…

剪映 自动打关键帧 AutoHotkey

牙叔教程 简单易懂 明确目的 做小说推文的话, 前面几分钟肯定要自己打关键帧, 所以这里的自动打关键帧指的是后面几分钟的图片, 对关键帧要求比较高的同学可以划走了, 因为这里介绍的是简单的 上上下下缩放的关键帧 要求 用剪映提取字幕…

【Python Twisted】零基础也能轻松掌握的学习路线与参考资料

Python Twisted是一个用于网络编程的事件驱动的框架,该框架使用异步I/O模型和回调函数。它支持多种协议,包括TCP、UDP、SSL/TLS、XMPP等,可以用来编写Web服务器、聊天应用、邮件服务器等。Twisted是一个成熟的框架,拥有强大的社区…

【JavaEE】文件操作和IO

目录 1、认识文件 1.1、路径 1.1.1 、绝对路径 1.1.2、相对路径 1.2、文本文件 vs 二进制文件 2、文件系统操作 3、文件内容操作 3.1、字节流用来输入的抽象类InputStream的方法使用 3.1.1、FileInputStream类的构造方法 3.1.2、字节流读操作 3.1.3、字节流写操作 3.…

Presto从入门到精通以及案例实操系列

1、简介 1.1、Presto的由来 Presto最初由Facebook公司开发,旨在解决Facebook内部大规模数据处理和数据分析的问题。在传统的Hadoop生态圈中,MapReduce作为数据处理框架,虽然能够处理海量数据,但是其查询性能却比较低下&#xff…