Python Web 开发之 JWT 简介
在之前的课程中,介绍过 Flask-Login 框架,它是基于 Session 和 Cookie 技术来实现用户授权和验证的,不过 Session 有很多的局限性,这一节介绍一种基于 token 的验证方式 —— JWT (JSON Web Token),除了对 JWT 的概念讲解之外,还有在 Flask 中简单实践
session 的局限性
基于 Session 的验证过程大体是:服务器端有一个 Session 词典,当用户验证登录后,在词典中为该用户创建一个 Session 对象,在响应( response )中返回一个 Session id,当用户下次请求时,携带 Session id,服务器从 Session 词典中可以恢复出 Session 对象,以完成用户的验证,在用 Session id 从恢复出认证实体。
从 Session 验证过程可以看出一些局限性:
-
服务器横向扩展很困难:因为 Session 只能存活在一个服务实例中,将用户请求引导到其他服务器,将丢掉用户的登录状态
-
携带信息量少,恢复会话信息比较耗时:Session 认证后,客户端得到 Session ID, 服务器无法从 Session ID 中得到更多信息,需要从数据库、文件系统或缓存中取得用户信息,比较耗时
-
没有统一标准:Session 由各个服务器框架自己实现,没有统一标准,存在应用扩展困难的问题,特别加密方式,五花八门,有很大的安全隐患
token 简介
为了解决 Session 的问题,有了 token 的验证方式。
token 可以理解成票据,或者凭证,当用户得到服务器的认证后,由服务器颁发,在之后的请求时携带,免去频繁登录。
token 不同于 Session 的地方:
-
可以独立于具体的服务器框架生成和校验
-
可以携带更多的信息,避免对持久层的查询操作
-
基于标准的算法可以由不同的节点完成验证
为了利用好 token 的验证机制,IEIT (互联网工程任务组),制定了基于 JSON 数据结构的网络认证方式 JWA(JSON Web Algorithms),还针对不同应用场景提出了具体协议,如 JWS、JWE、JWK 等,他们可以统称为 JWT,即 Javascript Web Token。
理解 JWA
JWA 的全称是 JSON Web Algorithms
JSON 是 Javascript 的语言的文本对象表示法,是一种独立语言环境的数据结构表示,可以用网络数据传输,在前面 RESTful 章节中,对 API 调用的返回数据格式就是 JSON。
Algorithms 本义是算法的意思,这里特指加密算法,也就是用 JSON 表示的数据,经过加密后在在服务器端和客户段之间传输。
有了数据结构和加密算法的基础,根据不同的应用场景,定义出了具体实现:
-
JWS(JSON Web Signature)对数据进行签名的,用于防止数据被篡改,传输不敏感数据的情况
-
JWE(JSON Web Encryption)对数据做了加密的,用于传输敏感数据,具有更好的安全性
-
JWK(JSON Web Key)是通过密钥对数据进行加密的方法,规定了相应的加密算法
JWT(JSON Web Token)上面 JWS、JWE 和 JWK 的总称。
JWT 简介
JWT Wiki 上的定义是:
JSON Web Token is an Internet standard for creating JSON-based access tokens that assert some number of claims.
大致意思是,JWT 是用基于 JSON 数据结构的生成包含了一些权限声明的网络访问凭证的网络标准
数据结构
JWT 由 Header
、Payload
和Signature
,三部分组成,像这样的形式:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJpc3MiOiJBdXRobGliIiwic3ViIjoiMTIzIiwibmFtZSI6ImJvYiJ9.
cBo6e7Uss5__16mlqZECjHJSKJDdyisevDP5cUGvJms
换行符只是为了展示用,实际 token 中不包括换行符
Header
用于指定采用的加密算法,以及 JWT 采用的形式类型,例如:
{
"alg" : "HS256",
"typ" : "JWT"
}
-
alg
指定前面所用的算法,默认为 HmacSHA256 简写为 HS256,还有 HS384、RS256 等 -
typ
是指令牌的类型,JWT 令牌的类型为JWT
Payload
用于携带一些信息,例如用户名,过期时间 等等,例如:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
JWT 标准定义了 7 个字段:
字段 | 说明 |
---|---|
iss | (issuer):签发人 |
exp | (expiration time):过期时间 |
sub | (subject):主题 |
aud | (audience):受众 |
nbf | (Not Before):生效时间 |
iat | (Issued At):签发时间 |
jti | (JWT ID):编号 |
这些字段有实现这自由选取,也可以加入其他自定义字段
Signature
首先,需要指定一个密钥(secret)。密钥很重要,需要严格保密
然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
即先将 header
和 payload
分别做 base64url 编码, 然后用 .
将他们连接成一个字符串,用加密算法,使用密钥 secret
, 得到的加密结果就算签名
Base64URL 编码字符集是 Base64 字符集的子集
=
被省略、+
替换成-
,/
替换成_
因为 token 可能通过 URL 进行传输,而=
、+
、/
在 URL 中有特殊含义
验证
当客户端发送请求时将 token 送到服务器端,可以用和签名同样的方式,重新计算一次签名,如果和客户端送过来的签名一致,说明 token 没有被篡改,如果不一致,说明 token 已被篡改,不安全了。
由此可见,用于做签名的密钥 secret 很重要,一旦泄漏,将无法鉴别 token 的真伪
JWT 应用
关于 Python 的 JWT 实现不止一个,不同的库,不同的实现方式层出不穷,今天要讲解的是 Python 的 Authlib 库,它是一个大而全的 Python Web 验证库支持多种 Python 框架
Authlib 的 JWT
Authlib 是构建 OAuth 和 OpenID 安全连接服务器的终极 Python 库,包括了 JWS, JWE, JWK, JWA, JWT
Authlib 功能强大而丰富,今天我们只了解他的 JWT 部分,之后在介绍基于第三方认证的 OAuth 技术时还会进一步讲解
安装
使用 pip 安装
pip install Authlib
如果一切正常,可以导入 Authlib 模板,例如,引入 jwt :
>>> from authlib.jose import jwt
>>>
小试牛刀
JWT 是服务器端的机制,所以可以在命令行中做测试
生成 token
>>> from authlib.jose import jwt
>>> header = {'alg': 'HS256'}
>>> payload = {'iss': 'Authlib', 'sub': '123', 'name': 'bob'}
>>> secret = '123abc.'
>>> token = jwt.encode(header, payload, secret)
>>> print(token)
b'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJpc3MiOiJBdXRobGliIiwic3ViIjoiMTIzIiwibmFtZSI6ImJvYiJ9.
cBo6e7Uss5__16mlqZECjHJSKJDdyisevDP5cUGvJms'
-
导入 jwt 模块
-
定义
header
,并且设置签名算法为HS256
-
定义
payload
,作为传输信息 -
定义
secret
,注意这里只是方便演示,实际项目中最好是随机生成,并妥善保存 -
使用 jwt 的
encode
方法,生成 token,encode
方法一次性实现了所有关于 JWT 协议的定义 -
打印出 token,可见,被
.
分隔为三部分,前两部分是header
和payload
的 Base64Url 编码,最后一部分是 签名
解码 token
接上面的环境:
>>> claims = jwt.decode(token, secret)
>>> print(claims)
{'iss': 'Authlib', 'sub': '123', 'name': 'bob'}
>>> print(claims.header)
{'alg': 'HS256', 'typ': 'JWT'}
>>> claims.validate()
>>>
-
用 jwt 模块的
decode
方法,利用secret
对token
进行解码,如果签名正确,就会得到解码内容,解码对象是authlib.jose.JWTClaims
类的实例 -
打印出解码内容,可以看到和生成 token 时的
payload
内容一致 -
打印出
header
,可以看到typ
为JWT
,即使用默认值 -
validate
方法用于检验 token 的有效性,比如:是否过期、主题是否一致,是否没到生效时间等等,也可以针对每种情况单独做验证,例如validate_exp
可用检验是否过期
虽然 JWT 理论很繁琐,但 Authlib 库提供了简洁的方法,让开发应用变得更高效
与客户端交互
JWT 之所有流行,有个重要原因是可以支持多种客户端,例如 浏览器和 app,JWT 标准规定,一般情况下,客户端需要将 token 放在 Http 请求的 Header 中的 Authorization 字段中,举个例子:
GET /resource HTTP/1.1
Host: server.example.com
Authorization: Bearer mF_9.B5f-4.1JqM
-
用 GET 方式请求
/resource
,在 Header 中添加了Authorization
字段 -
不能直接将 token 作为
Authorization
的值,必须有类型声明,这里是Bearer
Bearer
表示这个 token 是由认证服务器生成的,用来做身份识别的,除此之外,IEIT 还定义了其他 认证类型,如Bisic
,Digest
,可以简单理解成Bearer
就是 JWT 的认证类型
除了通过 Http Header 类携带 token 之外,还可以通过 POST 请求主体,以及 URL 中的 querystring 来向服务器发送 token,这两种情况下,需要使用 access_token 字段来表示 token
JWT 标准建议使用 Header 方式,除非 Header 无法使用时才考虑其他方式
Flask JWT
Authlib 主要的用途在打造一个 OAuth 应用,对于单独做 JWT 的实践有些麻烦,因此我们用 flask-jwt 框架,做 JWT 的实践。
flask-jwt 和之前讲述的 flask-login 用法很像,是基于 JWT 的认证的框架,提供和很多方便实践的特性
安装 flask-jwt
pip install Flask-JWT
创建应用
为了简单,将所有代码放在 app.py 中:
from flask import Flask
from flask_jwt import JWT, jwt_required, current_identity
from werkzeug.security import safe_str_cmp
# User 类,用于模拟用户实体
class User(object):
def __init__(self, id, username, password):
self.id = id
self.username = username
self.password = password
def __str__(self):
return "User(id='%s')" % self.id
# User 实体集合,用于模拟用户对象的缓存
users = [
User(1, 'user1', 'abcxyz'),
User(2, 'user2', 'abcxyz'),
]
username_table = {u.username: u for u in users}
userid_table = {u.id: u for u in users}
# 获取认证的回调函数,从 request 中得到登录凭证,返回凭证所代表的 用户实体
def authenticate(username, password):
user = username_table.get(username, None)
if user and safe_str_cmp(user.password.encode('utf-8'), password.encode('utf-8')):
return user
# 通过 token 获得认证主体的回调函数
def identity(payload):
user_id = payload['identity']
return userid_table.get(user_id, None)
app = Flask(__name__)
app.debug = True
app.config['SECRET_KEY'] = 'super-secret'
jwt = JWT(app, authenticate, identity) # 用 JWT 初始化应用
@app.route('/protected', methods= ["GET", "POST"]) # 定义一个 endpoint
@jwt_required() # 声明需要 token 才能访问
def protected():
return '%s' % current_identity # 验证通过返回 认证主体
if __name__ == '__main__':
app.run()
运行:
$ python app.py
* Serving Flask app "app" (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 566-326-511
获取 access_token
flask-jwt 默认的获取 token 的路由是/auth
,请求方式是 POST,用 JSON 传送用户名密码给服务器,例如:
$ curl -X POST -H "Content-Type: application/json" localhost:5000/auth -d '{"username":"user1","password":"abcxyz"}'
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
eyJleHAiOjE...<省略>...VudGl0eSI6MX0.
M-shnDPAVdu...<省略>...LaH1EMIbrWjPto"
}
如果登录凭证正确,则返回 access_token,可以看到被 .
分隔成三部分,即 JWT 的结构
使用 access_token
flask-jwt 默认通过 Header 传送 token,为了和 OAuth 生成的 JWT 做区分,默认使用JWT
作为 token 的类型,例如,用上面生成的 JWT 请求 /protected
:
curl -H "Authorization: jwt eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE...<省略>...VudGl0eSI6MX0.M-shnDPAVdu...<省略>...LaH1EMIbrWjPto" localhost:5000/protected
User(id='1')
如果 token 有效,则返回 token 对应的认证实体,这个例子中打印出了 user 实体
总结
本节课程讲解了基于 token 验证的 JWT,使用 Authlib 库对 JWT 做了实践练习,期望能帮助您更好的理解 JWT,最后通过 flask-jwt 模块,实践了 JWT 的验证方式,和使用方式。在后续的课程中还会对目前流行的第三方认证框架 OAuth 做介绍,敬请期待。
相关文章:
Python Web 开发之 JWT 简介
在之前的课程中,介绍过 Flask-Login 框架,它是基于 Session 和 Cookie 技术来实现用户授权和验证的,不过 Session 有很多的局限性,这一节介绍一种基于 token 的验证方式 —— JWT (JSON Web Token),除了对 JWT 的概念讲解之外&…...
科技资讯|荷兰电动自行车丢失将被拒保,苹果Find My可以减少丢失
荷兰最大的自行车协会荷兰皇家旅游俱乐部宣布,将不再为胖胎电动自行车提供保险,因为这种自行车的被盗风险极高。 随着电动自行车的销量飙升,胖胎也变得更受欢迎。但问题是,胖胎电动自行车也成为了自行车盗窃者的首选目标。ANWB …...
debian rules语法
当创建Debian软件包时,debian/rules 文件是非常重要的,它定义了软件包的构建规则。这个文件使用Makefile语法,指导构建、编译和安装软件包。下面将详细地介绍debian/rules文件的语法和常见用法。 基本结构: 一个简单的debian/rul…...
网易2023年Q2财报:营收240亿元,游戏技术跨产业创造数字就业
8月24日,网易发布2023年Q2财报。二季度,网易继续聚焦主营业务,业绩表现稳健;净收入240亿元,非公认会计准则下归属于公司股东的持续经营净利润90亿元,研发投入39亿元,相当于拿出近一半利润投入研…...
Python的Flask框架创建、运行与访问
天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…...
Java课题笔记~ 综合案例
3.综合案例 3.1 功能介绍 以上是我们在综合案例要实现的功能。除了对数据的增删改查功能外,还有一些复杂的功能,如 批量删除、分页查询、条件查询 等功能 批量删除 功能:每条数据前都有复选框,当我选中多条数据并点击 批量删除 按…...
Seaborn数据可视化(二)
目录 1.Seaborn风格设置 1.1 主题设置 1.2 轴线设置 1.3 移除轴线 1.4 使用字典传递函数 2.设置绘图元素比例 2.1 设置绘图元素比例paper 2.2 设置绘图元素比例poster 2.3 设置绘图元素比例notebook Seaborn将Matplotlib的参数划分为两个独立的组合,第一组用于…...
HDLBits-Verilog学习记录 | Verilog Language-Basics(1)
文章目录 3.Simple wire4.Four wires5.inverter | Notgate6. And gate7.Nor gate8.Xnorgate 3.Simple wire problem:Create a module with one input and one output that behaves like a wire. module top_module( input in, output out );assign out in;endmodule4.Four w…...
elementui表格嵌套上传文件直传到oss服务器(表单上传)
提示:记录项目中遇到的问题,仅供参考 文章目录 前言一、vue代码二、js接口请求代码 前言 项目需求是在表格中嵌套一个上传图片的功能,并且回显选择的图片和已上传的图片,再通过点击操作列中上传按钮才开始上传,使用的…...
使用navicat来访问doris
访问Doris的UI http:// dorisfe_ip:8030 由于doris是使用mysql协议,因此可以不用任何额外配置就可以使用navicat访问doris。 可以使用MySql客户端来连接Doris FE,也可以使用mysql命令工具连接,因为他是Mysql协议,所以在使用上跟M…...
2023国赛数学建模思路 - 案例:异常检测
文章目录 赛题思路一、简介 -- 关于异常检测异常检测监督学习 二、异常检测算法2. 箱线图分析3. 基于距离/密度4. 基于划分思想 建模资料 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 一、简介 – 关于异常…...
redis实战-缓存三剑客穿透击穿雪崩解决方案
缓存穿透 定义 缓存穿透 :缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库,造成数据库压力,也让缓存没有发挥出应有的作用 解决方案 缓存空对象 当我们客户端…...
Tomcat10安装及配置教程win11
Tomcat10安装及配置教程win11 Tomcat下载链接 Tomcat官网 Tomcat官网地址 https://tomcat.apache.org/ Tomcat的版本列表 点击上图中左侧红框内**Which version?**即可得下图 下载Tomcat 点击上图中左侧红框内红框内tomcat版本即可得下图,下载zip包 解压zip包…...
遗传算法解决TSP问题
一、求解问题概述 1.1 TSP问题 TSP问题是指旅行商问题(Traveling Salesman Problem)。在TSP问题中,假设有一名旅行商要在给定的一组城市之间进行旅行,每个城市只能被访问一次,并且旅行商必须最终返回出发城市。问题的…...
设计模式-工厂设计模式
核心思想 在简单工厂模式的基础上进一步的抽象化具备更多的可扩展和复用性,增强代码的可读性使添加产品不需要修改原来的代码,满足开闭原则 优缺点 优点 符合单一职责,每个工厂只负责生产对应的产品符合开闭原则,添加产品只需添…...
TM4C123库函数学习(3)---串口中断
前言 (1)学习本文之前,需要先学习前两篇文章。 (2)学习本文需要准备好TTL转USB模块。 函数介绍 ROM_GPIOPinConfigure() 配置GPIO引脚的复用功能。因为引脚不可能只有一个输出输入作用…...
opencv 进阶13-Fisherfaces 人脸识别-函数cv2.face.FisherFaceRecognizer_create()
Fisherfaces 人脸识别 PCA 方法是 EigenFaces 方法的核心,它找到了最大化数据总方差特征的线性组合。不可否认,EigenFaces 是一种非常有效的方法,但是它的缺点在于在操作过程中会损失许多特征信息。 因此,在一些情况下,…...
基于mysql5.7制作自定义的docker镜像,适用于xxl-job依赖的数据库,自动执行初始化脚本(ddl语句和dml语句)
一、背景 xxl-job-admin依赖mysql数据库,且需执行初始化脚本,包括ddl和dml语句。 具体的步骤总结如下: 1、新建数据库xxl_job2、创建mysql表table3、执行dml语句,包括新建admin用户及密码,创建执行器和任务。 毫无疑…...
LeetCodeHot100python版本:单调栈,栈,队列,堆
单调栈 739. 每日温度 42. 接雨水 双指针 单调栈(横向求解) 84. 柱状图中最大的矩形 栈和队列 队列:先入先出 栈:先入后出 两个栈 模拟 队列 一个队列 可以模拟 栈 20. 有效的括号 155. 最小栈 394. 字符串解码 堆 215. 数组中的第K个最大元素 3…...
JUC初识
JUC 是什么 java.util.concurrent 在并发编程中使用的工具包 从线程start 开始 package com.jhj.Thread;public class ThreadDemo {public static void main(String[] args) {Thread t1 new Thread(() -> {}, "t1");t1.start();} }start 方法调的是native sta…...
stm32之5.长按按键(使用时钟源)调整跑马灯速度
------------------------------ 源码 #include <stm32f4xx.h> #include "led.h" #include "delay.h" #include "my_str.h" #include "beep.h" #include "key.h" int main(void) { key_init(); Led_init();…...
element ui datePick时间日期一段时间,限制选择日期的范围
想限制只能选日期间隔为一年,联合选择器样式不好改,使用俩单独的 有两个办法限制 1.一个在外层使用form通过表单验证控制,出现错误提示(由于是两个单独的组件,触发验证的方式又为单个失去焦点,所以俩组件…...
kubernetes--技术文档-真--集群搭建-三台服务器一主二从(非高可用)-三服务器位于同交换机中
在使用k8s之前如果不太熟悉k8s的可以先看这个文章: kubernetes--技术文档--基本概念--《10分钟快速了解》_一单成的博客-CSDN博客 三节点相同安装操作: 1、设置hosts解析 根据角色在三个服务器中运行,设置自己的hostname。 标识…...
高性能MySQL实战(三):性能优化
大家好,我是 方圆。这篇主要介绍对慢 SQL 优化的一些手段,而在讲解具体的优化措施之前,我想先对 EXPLAIN 进行介绍,它是我们在分析查询时必要的操作,理解了它输出结果的内容更有利于我们优化 SQL。为了方便大家的阅读&…...
198. 打家劫舍
题目 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放…...
Pydev·离线git包
Pydev离线git包 1.下载离线git包:eclipse.egit.repository-4.4.0.201606070830-r.zip 2.将解压后目录:eclipse.egit.repository-4.4.0.201606070830-r\plugins下的jar文件放到 ide\eclipse\plugins目录下 3.重启pydevIDE 百度搜索站长工具:h…...
Vue-12.集成postcss.config.js
PostCSS 介绍 PostCSS 是一个用于处理样式的工具,可以通过插件来定制其行为。以下是一些常用的 PostCSS 插件和 API 的介绍: Autoprefixer: 这是一个流行的 PostCSS 插件,用于自动添加浏览器前缀,以确保您的样式在不同浏览器中具…...
基于前端技术原生HTML、JS、CSS 电子病历编辑器源码
电子病历系统采取结构化与自由式录入的新模式,自由书写,轻松录入。实现病人医疗记录(包含有首页、病程记录、检查检验结果、医嘱、手术记录、护理记录等等。)的保存、管理、传输和重现,取代手写纸张病历。不仅实现了纸…...
Linux环境下远程访问SVN服务:SVN内网穿透的详细配置与操作指南
文章目录 前言1. Ubuntu安装SVN服务2. 修改配置文件2.1 修改svnserve.conf文件2.2 修改passwd文件2.3 修改authz文件 3. 启动svn服务4. 内网穿透4.1 安装cpolar内网穿透4.2 创建隧道映射本地端口 5. 测试公网访问6. 配置固定公网TCP端口地址6.1 保留一个固定的公网TCP端口地址6…...
创建k8s operator
目录 1.前提条件 2.进一步准备 2.1.安装golang 2.2.安装code(vscode的linux版本) 2.3.安装kubebuilder 3.开始创建Operator 3.1.什么是operator? 3.2.GV & GVK & GVR 3.3.创建operator 3.3.1. 生成工程框架 3.3.2.生成api(GVK) …...
wordpress个人站主题/ping站长工具
在这里我试图上传pdf,doc和docx文件。 PDF文件正在上传,但doc和docx文件未上传。我在form标记中保留了enctype"multipart/form-data"属性。我的代码有什么问题。if ((($_FILES["uploadjob"]["type"] "application/p…...
大连培训通网站建设/怎么做网络营销平台
1.ASP.NET运行原理概述 如上图,当一个http请求发送过来并被IIS机收到之后,IIS首先通过你请求的页面类型为其加载相应的dll文件,然后在处理过程中将这条请求发送给能够处理这条请求的模块,而在ASP.NET中这个模块就叫做HttpHandler,为什么aspx这样的文件可…...
身高差效果图网站/seo排名怎么做
1.应用场景 主要用于使用ES做搜索时,了解分析器,分词器,过滤器的工作原理与流程 比如根据业务实现区分大小写的查询,模糊查询中区分大小写 了解其中的原理以及应对方案。 2.学习/操作 1.文档阅读 Elasticsearch分析器结构组成 - …...
毛绒玩具 东莞网站建设 技术支持/国际最新十大新闻事件
http://blogold.chinaunix.net/u3/110505/showart_2223811.html 以太网接口可分为协议层和物理层。 协议层是由一个叫MAC(Media Access Layer,媒体访问层)控制器的单一模块实现。 物理层由两部分组成,即PHY(Physical Layer,物理层)和传输器。…...
电子商务网站界面设计实验报告/温州seo服务
谷歌人工智能部门DeepMind在预测蛋白质结构方面迈出了一大步。公司表示,DeepMind开发的AlphaFold系统已经解决了关键的“蛋白质折叠问题”,并将解决问题的运算时间从数月缩短至数小时,这有助于加快药物发现速度,有可能破解一个类似…...
上海网站推广公司/厦门网站建设公司
功能 说明 查看app通过Log类输出的日志. 日志类型 系统信息,异常时堆栈信息,开发者输出信息. 内容 介绍logcat指令.UI操作可用Android Studio查看. 日志系统 说明 安卓的日志系统是由系统进程logd进行管理.logd将部分日志通过循环链表缓存. 缓存 日志缓冲集合: main,crash,syst…...