Metadata-Version: 2.1
Name: graphql-schema-parse
Version: 0.2.0
Summary: Graphql文档解析工具，提供解析成前端/Postman可用的query语句(.gql)或者RESTFul可使用的(.json)文件能力
Home-page: https://github.com/zy7y/graphql-schema-parse.git
License: MIT
Keywords: graphql,restful,parse,gql,test
Author: 柒意
Author-email: 396667207@qq.com
Requires-Python: >=3.9,<4.0
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.9
Requires-Dist: Jinja2 (>=3.0.3,<4.0.0)
Requires-Dist: graphql-core (>=3.2.0,<4.0.0)
Requires-Dist: typer (>=0.4.0,<0.5.0)
Project-URL: Repository, https://github.com/zy7y/graphql-schema-parse.git
Description-Content-Type: text/markdown

# graphql_schema_parse
> 解析GraphQL文档，并提供将其转成**.gql**(前端查询可用得query字符串)，**.json**(requests可用得json关键字参数接收数据)

## [GraphQL](https://graphql.cn/)
> GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时，详细内容点击标题访问官网
在实际工作种，最常用的是 query(查询), mutation(更改/新增), subscription

当发起一个GraphQL请求之后，通过抓包能够发现，最终和RESTFul发送请求没多大区别，它指定了JSON格式传参数，大致如下
![](images/发送graphq.png)
![](images/graphql请求数据.png)
```json
{
  "query": " query users {\n        users{\n                  id\n                  username\n                 }\n             \n        }\n        ",
  "variables": {},
  "operationName": "users"
}
```
```json
{
  "query": "mutation addUser($username: String!, $password: String!) {\n  addUser(username: $username, password: $password) {\n    id\n    username\n  }\n}\n",
  "variables": {
    "username": "gql",
    "password": "gql1"
  },
  "operationName": "addUser"
}
```
```json
{
  "query": "mutation addUserInput($user: AddUserInput!) {\n  addUserInput(user: $user) {\n    id\n    username\n  }\n}\n",
  "variables": {
    "user": {
      "username": "haha",
      "password": "gg"
    }
  },
  "operationName": "addUserInput"
}
```

- query: 其实就是生成的查询部分语句，前端传字段后端定义有返回
- variables: 使用query语句中的变量名
- operationName: 则是后端在实现时指定的接口名称(暂时这么理解吧)
![](images/介绍.png)
**这里用的Python语言，实际 `_` 会被转换成 `驼峰写法`**

## GraphQL示例应用
> 提供的GraphQL示例应用源码地址：https://gitee.com/zy7y/starlette-example
### 源码使用
1. 克隆
```shell
git clone https://gitee.com/zy7y/starlette-example
```
2. 安装依赖
```shell
pip install -r requirements.txt 
pip install strawberry-graphql[debug-server]
```
![](images/依赖安装.png)
3. 启动
```shell
cd injection_service\graphql
strawberry server schema 
```
![](images/微信截图_20220126162625.png)
**访问：http://127.0.0.1:8000**
![](images/微信截图_20220126163024.png)
### 通过url获取接口文档
``` shell
# 转JSON
gql parse http://127.0.0.1:8000 目录地址

# 转GQL
gql parse http://127.0.0.1:8000 --to gql 目录地址

# 转sqlmap(-r HTTP请求信息.txt)
# 带json
gql parse http://127.0.0.1:8000 --headers .\examples\headers.json --to sqlmap .\examples\sqlmap（json）示例
# 不带json
gql parse http://127.0.0.1:8000 --to sqlmap .\examples\sqlmap示例
```
**需要Token认证**
```json5
// 新建headers.json 如下
{
"Authorization": "Bearer token"
}
```
```shell
gql parse http://127.0.0.1:8000 --headers headers.json 目录地址
```
![url获取示例](images/urlheaders.png)
## 使用graphql-schema-parse
### 安装
```shell
pip install graphql-schema-parse
```

### 通过SDL获取接口文档
1. 前置条件
```shell
# 在执行启动服务相同目录下执行, 得到SDL
strawberry export-schema schema > schema.graphql
```
![](images/sdl.png)
2. 通过graphql文件转换成gql
**sdl文件必须是utf-8编码，不是则自行修改**
```shell
gql parse examples\schema.graphql --to gql 目录地址
```
![](images/togql.png)

## 测试
1. gql文件(查询-query)
**将生成的users.gql 文件内容复制到127.0.0.1:8000当中**
![](images/query.png)
2. gql文件(突变-mutation)
**将生成的addUser.gql 文件内容复制到127.0.0.1:8000当中**
![](images/add_user.png)
3. json文件(查询-query)
**将生成的users.json 文件内容赋值给`data`，使用requests包发送请求，代码如下**
```python
from requests import post

url = "http://127.0.0.1:8000/graphql"
data = {
    "query": " query users {\n        users{\n                  id\n                  username\n                 }\n             \n        }\n        ",
    "variables": {}, "operationName": "users"}
print(post(url, json=data).json())
```
![](images/gql-restful.png)
4. json文件(突变-mutation)
**将生成的addUsers.json 文件内容赋值给`data`，使用requests包发送请求，代码如下**
```python
from requests import post

url = "http://127.0.0.1:8000/graphql"
data = {
    "query": " mutation addUserInput ($user: AddUserInput!){\n        addUserInput (user: $user){\n                  id\n                  username\n                 }\n             \n        }\n        ",
    "variables": {"user": {"username": "", "password": ""}}, "operationName": "addUserInput"}
print(post(url, json=data).json())

```
![](images/json-restful.png)
5. txt文件(sqlmap -r httpinfo.txt， 可用于sqlmap sql注入扫描)
**addUserInput.txt文件内容**
```text
POST /graphql HTTP/1.1
HOST: http://127.0.0.1:8000
Authorization: Bearer token
Content-Type: application/json

{"query": " mutation addUserInput ($user: AddUserInput!){\n        addUserInput (user: $user){\n                  id\n                  username\n                 }\n             \n        }\n        ", "variables": {"user": {"username": "*", "password": "*"}}, "operationName": "addUserInput"}
```
```shell
# 安装sqlmap
pip install sqlmap

# 进行SQL注入扫描， sqlmap详细用法前往sqlmap官网学习
sqlmap -r addUserInput.txt --level 5 --risk 3
```
**扫描过程中**
![](images/sqlmap执行过程.png)
![](images/执行时服务被不断请求.png)
![](images/入库数据.png)
**扫描结果（获取到了我的数据库为SQLlite）**
![](images/注入结果.png)

# 参数详情
```shell
gql parse --help 
```
output:
```shell
Usage: cli.py parse [OPTIONS] FROM_PATH TO_DIRECTORY

  将Graphql接口文档转成gql文件/Json文件 :param from_path: 接口文档地址, 本地JSON文件地址(.json) 或者 本地
  SDL文件(.schema ), 或者 服务器URL填入(服务器的IP:PORT) :param to: 转换之后的文件类型, 可选
  TO_DIRECTORY  生成文件保存目录，不存在时，自动创建  [required]

Options:
  --headers TEXT   url方式获取接口文档时，可选项传入请求头json文件地址
  --to [json|gql]  [default: ToType.to_json]
  --depth INTEGER  query语句体中可用查询字段递归深度  [default: 1]
  --help           Show this message and exit.

```

