百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 小说推荐 > 正文

拣宝_拣宝最新章节_拣宝大结局 - 笔趣阁 - fd80s

ann3311 2025-07-27 22:14 2 浏览

史诗级:3万字深锐观察,下半年中国市场高音质耳机半年鉴!

写在前面

实现一个具备 RSA 加解密的功能并不难,使用任何一门“具备流行度”的语言,调用相关函数库/模块进行操作即可,一般只需要两步:

  • 创建或加载 RSA KEY(s)。
  • 设置使用算法等参数,进行计算,得到结果。

但是,即使我们需要提供一个最简单的无需鉴权的开放接口,还会有非常多的额外工作要做,诸如:如何提供基础 Web 服务,如何进行云端架构设计,如何高效利用服务器资源,如何保证服务质量,如何进行监控…然而,以上多数的事情都偏离了我们最初的初衷,需要额外编写或进行大量的设置。有没有更省事的方案呢?

众所周知,Nginx 是一个高性能的 Web 服务器,易于部署,同时又具备很强的可扩展性,如果在上面添加我们所需要的功能,这个开放接口的需求不就能以最小代价实现了嘛?

社区里其他方案和不足之处

在实现之前,我在开源社区中进行了简单的调研,发现这个需求目前已有两个实现:

  • https://github.com/spacewander/lua-resty-rsa
  • https://github.com/LittleLiByte/lua-rsa

这两个实现,都是基于 Nginx 衍生版 OpenResty 的模块,两者功能上的重要区别在于前者只支持基于公钥加密私钥解密,而对于私钥加密公钥解密的方式却不支持,后者则进行了这个功能的补全;在实现上的差异主要在于前者重度使用了 LUA FFI 这个允许以 LUA 代码调用外部 C 函数库的库,将 OpenSSL 中关于 RSA 加解密的函数导入了 LUA 模块,而后者虽然也使用了相同的方案,不同的地方在于,使用了自行构建的 RSA 库来进行 OpenSSL 函数库的调用,在执行效率上有了很大的进步(在压测过程中,CPU 一度达到 %+)。

不知是作者和我一样对于 C 语言并不“熟练”,还是倾向于使用 LUA,代码直接使用了年3月国外一位技术博客作者 Ravishanker Kusuma 的示例代码:RSA Encryption & Decryption Example with OpenSSL in C。

上面这段示例代码,或许也启发了前文中第一个库的方案,在 年 月的时候,初代作者 doujiang24 的提交中对于加解密的方式和上面文章如出一辙:
https://github.com/spacewander/lua-resty-rsa/commit/9262c57e89fd3c554e6625cddead20781d34b43b,相比较原作者的示例代码,这个提交中可以看到作者添加了针对“包含密码保护的私钥”的加载处理。

不过,既然都考虑编译 C 语言函数库了,为什么不考虑再更进一步呢?尤其是针对这类持久不易变化的功能。直接编译成 Nginx 模块,显然可以获得更多的性能福利。

编写 Nginx 模块:完成基础计算部分

为了尽可能让文章简单,我将上面的代码进行了一定的精简和调整,只实现私钥加密的功能,并对外部使用的变量做了清理操作,减少了原始代码中内存溢出的问题,其他函数实现类似,在此就不多赘述。

考虑到 RSA 加密后的内容可读性不高,于是额外引入了一个简单的 Base64 编码实现。

#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/buffer.h>

#include <stdio.h>
#include <string.h>

char privateKey[] = &#;-----BEGIN ENCRYPTED PRIVATE KEY-----\n&#;
                    &#;MIIJrTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQICTqoISmC8M0CAggA\n&#;
                    ... ...
                    &#;onL8DKhku9s/5NB+eEVC3v4JubSfph0GEiVemMIQxMI2\n&#;
                    &#;-----END ENCRYPTED PRIVATE KEY-----\n&#;;

char *passphrase = &#;soulteary.com&#;;

int encrypt(unsigned char *data, int data_len, unsigned char *encrypted)
{
    BIO *keybio;
    keybio = BIO_new_mem_buf(privateKey, -1);

    RSA *rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, passphrase);
    int ret_len = RSA_private_encrypt(data_len, data, encrypted, rsa, RSA_PKCS1_PADDING);

    BIO_free(keybio);
    RSA_free(rsa);

    return ret_len;
}

char *base64(const unsigned char *input, int length)
{
    BIO *bmem, *b64;
    BUF_MEM *bptr;

    b64 = BIO_new(BIO_f_base64());
    bmem = BIO_new(BIO_s_mem());
    b64 = BIO_push(b64, bmem);
    BIO_write(b64, input, length);
    BIO_flush(b64);
    BIO_get_mem_ptr(b64, &bptr);

    char *buff = (char *)malloc(bptr->length);
    memcpy(buff, bptr->data, bptr->length - 1);
    buff[bptr->length - 1] = 0;

    BIO_free_all(b64);

    return buff;
}

int main()
{

    char raw[ / 8] = &#;{\&#;key\&#;: \&#;val\&#;}&#;;
    unsigned char encrypted[] = {};

    int encrypted_length = encrypt(raw, strlen(raw), encrypted);
    if (encrypted_length == -1)
    {
        printf(&#;Encrypt failed&#;);
        exit(0);
    }

    char *result = base64(encrypted, encrypted_length);

    printf(&#;%s\n&#;, result);

    exit(0);
}

为了更方便的测试功能,将上面的内容保存为 encrypt.c,然后编写一个 Dockerfile 用于基础计算部分的编译测试(这里需要注意编译顺序,避免编译不通过):

FROM alpine: AS Builder

RUN cat /etc/apk/repositories | sed -e &#;s/dl-cdn.alpinelinux.org/mirrors.aliyun.com/&#; | tee /etc/apk/repositories
RUN apk add openssl-dev libressl-dev gcc g++
COPY ./encrypt.c /
RUN cd / && \
	gcc encrypt.c -lssl -lcrypto -o encrypt && \
	cp encrypt /bin/

使用 docker build -t test . 构建一个临时的容器,然后使用 docker run --rm -it test encrypt 测试程序,会得到类似下面的结果。

rFKPHoJPR4iExWgx6EFzLVA4uISNyxYDtmOlGT+e6SBy9SPDve4o5YNzSbX1grnj
bCFwvp80SwJzs1yaFzChDxo7HTdV3hK3syba+8zHw05FBeuw4/q8zn4e+KAv5QjE
KzrQvMlzE1XsPrbI+IjJpqGIrpy57VBVr8CpmT/RajqZ42fy/cgn429i3NJhlckW
vVPbY7x3vcXC/5FcRwR9hqPJ2qVXulVH/SxQ422bmLigFHwnWjT0qnDVTvgQFeQd
1edmJzPgbhycmGPvCdjRvN80eEX8lp3Oz92uACXfeReab26R0vhgGysPv3w97vdN
TPmt9l1eyeWSnYR/gWU9HSM7FbAJyvKLp5h07X4AYyf2uDl7DxWIJp+ZG/IxzCzt
2IzKN2siq2bqvJEqR7+wDS2ttgCzD2ogmMMiQFgAa1yDruRasSJbV408n7STmE6h
Z6klL8C+zXwgOLYnDi7bNVUhz6BkqHrt+utKql6zr0lKdOywwqElOQJeostBknH5
OCcoazuu+ZOOeAT3DoRLRVqHp/v75aIW9nYJmNjCqgonYrw9flKezh04nlSCjDaF
DYJKVUSsL0mAhGMxfcVWrEzWOTAIOvg6U3vshSpDKk3KCaRhamWxCMVItfBNeeHL
T8ZYF0tHz/cLkBm1wSNOuTxaGQRD/ZH0lSQGP8Aq4x4=

在验证完毕基础功能可行后,我们来看看怎么将它编写为一个 Nginx 可以调用的模块。

编写 Nginx 模块:按照 Nginx 模块要求进行改写

这里先不考虑让 Nginx 从请求中获取数据动态改变计算结果,仅做简单的代码调整,让 Nginx 能够调用我们之前实现的函数。

#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>

#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/buffer.h>

char privateKey[] = &#;-----BEGIN ENCRYPTED PRIVATE KEY-----\n&#;
                    &#;MIIJrTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQICTqoISmC8M0CAggA\n&#;
                    ... ...
                    &#;onL8DKhku9s/5NB+eEVC3v4JubSfph0GEiVemMIQxMI2\n&#;
                    &#;-----END ENCRYPTED PRIVATE KEY-----\n&#;;

char *passphrase = &#;soulteary.com&#;;
int rsa_encrypt(unsigned char *data, int data_len, unsigned char *encrypted)
{
    BIO *keybio;
    keybio = BIO_new_mem_buf(privateKey, -1);
    OpenSSL_add_all_algorithms();
    RSA *rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, passphrase);

    int encrypted_length = RSA_private_encrypt(data_len, data, encrypted, rsa, RSA_PKCS1_PADDING);

    BIO_free(keybio);
    RSA_free(rsa);

    return encrypted_length;
}

char *base64(const unsigned char *input, int length)
{
    BIO *bmem, *b64;
    BUF_MEM *bptr;

    b64 = BIO_new(BIO_f_base64());
    bmem = BIO_new(BIO_s_mem());
    b64 = BIO_push(b64, bmem);
    BIO_write(b64, input, length);
    BIO_flush(b64);
    BIO_get_mem_ptr(b64, &bptr);

    char *buff = (char *)malloc(bptr->length);
    memcpy(buff, bptr->data, bptr->length - 1);
    buff[bptr->length - 1] = 0;

    BIO_free_all(b64);

    return buff;
}

static char *ngx_http_encrypt(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_int_t ngx_http_encrypt_handler(ngx_http_request_t *r);

static ngx_command_t ngx_http_encrypt_commands[] = {
    {ngx_string(&#;encrypt&#;),
     NGX_HTTP_LOC_CONF | NGX_CONF_NOARGS,
     ngx_http_encrypt,
     0,
     0,
     NULL},
    ngx_null_command};

static ngx_str_t will_encrypt_string;

static ngx_http_module_t ngx_http_encrypt_module_ctx = {
    NULL, /* preconfiguration */
    NULL, /* postconfiguration */

    NULL, /* create main configuration */
    NULL, /* init main configuration */

    NULL, /* create server configuration */
    NULL, /* merge server configuration */

    NULL, /* create location configuration */
    NULL  /* merge location configuration */
};

ngx_module_t ngx_http_encrypt_module = {
    NGX_MODULE_V1,
    &ngx_http_encrypt_module_ctx, /* module context */
    ngx_http_encrypt_commands,    /* module directives */
    NGX_HTTP_MODULE,              /* module type */
    NULL,                         /* init master */
    NULL,                         /* init module */
    NULL,                         /* init process */
    NULL,                         /* init thread */
    NULL,                         /* exit thread */
    NULL,                         /* exit process */
    NULL,                         /* exit master */
    NGX_MODULE_V1_PADDING};

static ngx_int_t ngx_http_encrypt_handler(ngx_http_request_t *r)
{
    ngx_int_t rc;
    ngx_buf_t *b;
    ngx_chain_t out;

    /* we response to &#;GET&#; and &#;HEAD&#; requests only */
    if (!(r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD)))
    {
        return NGX_HTTP_NOT_ALLOWED;
    }

    /* discard request body, since we don&#;t need it here */
    rc = ngx_http_discard_request_body(r);

    if (rc != NGX_OK)
    {
        return rc;
    }

    /* set the &#;Content-type&#; header */
    r->headers_out.content_type_len = sizeof(&#;text/html&#;) - 1;
    r->headers_out.content_type.len = sizeof(&#;text/html&#;) - 1;
    r->headers_out.content_type.data = (u_char *)&#;text/html&#;;

    /* send the header only, if the request type is http &#;HEAD&#; */
    if (r->method == NGX_HTTP_HEAD)
    {
        r->headers_out.status = NGX_HTTP_OK;
        r->headers_out.content_length_n = will_encrypt_string.len;

        return ngx_http_send_header(r);
    }

    /* allocate a buffer for your response body */
    b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
    if (b == NULL)
    {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    char *preset_words = &#;hi&#;;
    will_encrypt_string.data = (u_char *)preset_words;
    will_encrypt_string.len = strlen(preset_words);

    unsigned char *test_data = (unsigned char *)will_encrypt_string.data;
    int data_len = will_encrypt_string.len;

    unsigned char rsa_encrypted[] = {};
    int encrypted_length = rsa_encrypt(test_data, data_len, rsa_encrypted);

    char *base64_data = base64(rsa_encrypted, encrypted_length);
    will_encrypt_string.data = (u_char *)base64_data;
    will_encrypt_string.len = ngx_strlen(will_encrypt_string.data);

    /* attach this buffer to the buffer chain */
    out.buf = b;
    out.next = NULL;

    /* adjust the pointers of the buffer */
    b->pos = will_encrypt_string.data;
    b->last = will_encrypt_string.data + will_encrypt_string.len;
    b->memory = 1;   /* this buffer is in memory */
    b->last_buf = 1; /* this is the last buffer in the buffer chain */

    /* set the status line */
    r->headers_out.status = NGX_HTTP_OK;
    r->headers_out.content_length_n = will_encrypt_string.len;

    /* send the headers of your response */
    rc = ngx_http_send_header(r);

    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only)
    {
        return rc;
    }

    /* send the buffer chain of your response */
    return ngx_http_output_filter(r, &out);
}

static char *ngx_http_encrypt(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_core_loc_conf_t *clcf;

    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
    clcf->handler = ngx_http_encrypt_handler;

    return NGX_CONF_OK;
}

将上面的内容保存为 ngx_http_encrypt_module.c,然后编写模块所需要的声明文件:

ngx_addon_name=ngx_http_encrypt_module

if test -n &#;$ngx_module_link&#;; then
    ngx_module_type=HTTP
    ngx_module_name=$ngx_addon_name
    ngx_module_incs=
    ngx_module_deps=
    ngx_module_srcs=&#;$ngx_addon_dir/ngx_http_encrypt_module.c&#;
    ngx_module_libs=
   . auto/module
else
    HTTP_MODULES=&#;$HTTP_MODULES ngx_http_encrypt_module&#;
    NGX_ADDON_SRCS=&#;$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_encrypt_module.c&#;
fi

在编译文件之前,我们先进行 Nginx 配置文件的编写:

load_module modules/ngx_http_encrypt_module.so;

user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;


events {
    worker_connections  ;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  &#;$remote_addr - $remote_user [$time_local] &#;$request&#; &#;
                      &#;$status $body_bytes_sent &#;$http_referer&#; &#;
                      &#;&#;$http_user_agent&#; &#;$http_x_forwarded_for&#;&#;;

    access_log  /var/log/nginx/access.log  main;

    keepalive_timeout  ;

    gzip  on;

    server {
        listen       ;
        server_name  localhost;

        location / {
            encrypt;
        }
    }
}

我这里使用 Nginx 默认配置进行简单修改,在文件头部声明加载接下来编译生成的动态模块,在 location 配置中添加我自定义的 encrypt 指令,然后将上面的内容保存为 nginx.conf 等待后面使用。

接着,借助我之前文章《如何在容器时代高效使用 Nginx 三方模块》中提到过的 工具镜像,就能进行快速进行 Nginx 模块的编译开发了,还是先来编写一个用于编译插件的 Dockerfile:

FROM soulteary/prebuilt-nginx-modules:base--alpine AS Builder
COPY src/config /usr/src/encrypt/
COPY src/ngx_http_encrypt_module.c /usr/src/encrypt/
WORKDIR /usr/src/nginx
RUN CONFARGS=$(nginx -V 2>&1 | sed -n -e &#;s/^.*arguments: //p&#;) \
    CONFARGS=${CONFARGS/-Os -fomit-frame-pointer -g/-Os} && \
    echo $CONFARGS && \
    ./configure --with-compat $CONFARGS --add-dynamic-module=../encrypt && \
    make modules

FROM nginx:-alpine
COPY nginx.conf /etc/nginx/nginx.conf
COPY --from=Builder /usr/src/nginx/objs/ngx_http_encrypt_module.so /etc/nginx/modules/

还是执行 docker build -t test . 构建一个基础镜像,然后执行 docker run --rm -it -p : test 来进行功能测试。浏览器或终端访问本地的 端口,不出意外,能够看的我们预期中 RSA 加密后的内容被正确的 Base64 编码后展示了出来。

使用 wrk 之类的软件进行压力测试,会发现相比较使用 Lua 方案,使用纯 Nginx 模块的方案,CPU 负载从 % 左右降低到了个位数,甚至持续稳定在 1% 以内,结果还是比较惊艳的。

编写 Nginx 模块:改进模块,支持参数

接下来,我们来进行一个最常规的功能支持,让模块能够接受请求参数,并根据参数的变化,动态计算结果。

...
/* allocate a buffer for your response body */
b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
if (b == NULL)
{
    return NGX_HTTP_INTERNAL_SERVER_ERROR;
}

ngx_str_t var_user = ngx_string(&#;arg_user&#;);
ngx_uint_t key_user = ngx_hash_key(var_user.data, var_user.len);
ngx_http_variable_value_t *val_user = ngx_http_get_variable(r, &var_user, key_user);

if (val_user != NULL && val_user->not_found != 1)
{

    char *tpl;
    asprintf(&tpl, &#;{\&#;name\&#;:\&#;%s\&#;}&#;, (char *)val_user->data);

    will_encrypt_string.data = (u_char *)tpl;
    will_encrypt_string.len = strlen(tpl);
    free(tpl);
}
else
{
    char *preset_words = &#;hi&#;;
    will_encrypt_string.data = (u_char *)preset_words;
    will_encrypt_string.len = strlen(preset_words);
}

unsigned char *test_data = (unsigned char *)will_encrypt_string.data;
int data_len = will_encrypt_string.len;

...

上面的代码展示了如何读取 GET 请求中的 user 参数,并将参数安全的拼合到字符串模版中,进行计算。相信即使你不熟悉 C 语言,参考上面的代码也可以快速进行调整,将计算逻辑调整到符合你预期的方式。

如果你希望模块能够非编译环境快速复用,可以参考其他的 Nginx 插件源代码,“实现 Nginx 读取静态文件”的功能,将编译至模块中的证书剥离出来。不过,如果你有 CI 环境,能够方便的持续获取最新的构建结果,将证书编译至模块中,可以获得更高的绝对性能。

其他

关于 Nginx 模块的开发,我个人建议阅读 Nginx 官方开发文档 和 Nginx 源代码,相比较国内外陈旧的文档,可以节约不少时间。

如果你对于加密内容的长度有特殊要求,需要加密特别长的内容,我建议你阅读这篇文章,考虑使用 EVP 函数替换文中的函数执行加密过程:Simple Public Key Encryption with RSA and OpenSSL。

最后

下一篇文章,我将聊聊我将本文中的功能用到了哪里。

相关推荐

都市保镖类小说推荐 - 起点中文网

5本都市保镖文:他无意间成为冰冷气质美女总裁的保镖1.《我的冷艳总裁老婆》-百里龙虾-字数:万-标签:保镖、冰山女总裁、小姨闺蜜攻略-推荐指数:★★★★-经典语录:“保镖弟弟,今晚来我房间...

《人间仙路》(校对全本) 作者:何常在 TXT 免费下载_《人间仙路》(校对全本) 作者:何常在 TXT 在线阅读 奇书楼

作家何常在:网络文学的说法早晚会消失,只留下文学各位书友们,大家好。我是旧言心雨!今天给大家推荐几本玄幻文,如果也喜欢这类型的小说,还请多多留言点赞呀!第一本《斗破苍穹》简介:这里是属于斗气的世界,...

邪性总裁(五枂)_邪性总裁小说全文免费阅读-修罗小说

小说:地痞忽然发疯,拿枪对同伙穷追不舍,一只黄鼠狼紧随在后丛林遇险耽误了两天两夜,接下来的时间,被古飞与苗菲菲全部用在赶路上。庆幸的是二人吞服了造化丹之后,体质得到了大幅度的改善,纵然走上半天山路都不...

近战保镖最新章节_无弹窗全文免费阅读_笔趣阁

第六百二十四章:保镖?《逃离塔科夫》攻略百科,全任务奖励+全地图信息+角色装备模组详解。《逃离塔科夫》是一款硬核仿真的第一人称动作类角色扮演游戏/模拟游戏,同时兼具大型多人在线游戏(MMO)的特色...

傲世丹神免费阅读-沈翔-免费小说全文-作者-寂小贼作品-七猫中文网

傲世丹神(沈翔白幽幽)寂小贼小说免费阅读最新章节各位书友们,大家好,我是小新!又到了给大家分享小说的时刻了。长篇玄幻爽文小说大家看的不少了,那在众多的长篇玄幻爽文小说中,你知道有哪几本好看到爆的长篇玄...

巅峰赘婿小说最新章节_巅峰赘婿免费无弹窗_笔趣阁

巅峰赘婿全文第章免费阅读:剑如霜,你终于肯出现了“你先回去吧,我看到了一个熟人,过去跟他唠唠嗑。”张纯良的表情又恢复到了原来的样子。“那好,你记得早点回来啊。”夏青衣眼里的光芒闪了闪,随即便接过钥匙,...

月上重火全文阅读-天籁纸鸢-月上重火免费阅读-落霞小说

《月上重火》:IP改编剧还需要下更大的功夫据北京法院审判信息网今日发布的公开裁判文书信息,上海时悦文化传媒有限公司与上海张翰影视文化工作室合同纠纷二审已于3月日判决,判决结果维持一审结果,时悦返还张翰...

斗罗大陆4终极斗罗30册在线阅读
斗罗大陆4终极斗罗30册在线阅读

《斗罗大陆Ⅳ终极斗罗》是《斗罗大陆》系列的第四部,讲述的是《斗罗大陆III龙王传说》一万年后的故事,作品继承了《斗罗大陆》系列的诸多设定。斗罗联邦科考队在极北之地科考时发现了一个有着金银双色花纹的蛋,用仪器探察之后,发现里面居然有生命体征,...

2025-08-23 00:00 ann3311

豪门宠媳(五枂)_ 豪门宠媳全本小说免费阅读_毕业论文网

豪门宠媳记:向太买地如买菜,郭碧婷的后花园藏着婆媳情深密码当妈的在豪门当保姆供儿子挥霍,债台高筑还在周边城市每周逛吃,岁巨婴啃老啃得理直气壮。年7月初,简衣笔下普通保姆丽芳再次因儿子欠债登上热搜,这已...

玄学大师的悠闲生活 (柔桡轻曼)_玄学大师的悠闲生活最新章节_新笔趣阁

九篇玄学文推荐,收藏《我种的田很养生》by小小船《当林黛玉穿成娱乐圈新人之后》by南否《太子来到现代后》by苏格拉提拉米苏《我在大学做厨神》by靳冉《从全民奶包到世界冠军》by不晓轻寒《我做菜很好...

韩三千苏迎夏最新章节_韩三千苏迎夏全文免费阅读,韩三千苏迎夏

小说:赘婿回到家中,却没想丈母娘冷着脸,以后生活费只给他五百苏迎夏回到自己房间的时候,韩三千正好喝完最后一口面汤,正准备起身扔掉面盒,苏迎夏挡在了面前。“我帮你扔。”韩三千还没反映过来,苏迎夏已经把盒...

剑尊叶玄叶灵完整版 - 第一笔趣阁

小说:他被说是天选之人,实力逆天,可在少女眼中只不过是蝼蚁安澜秀!叶玄也是愣住了。因为这个名字,他是听过的,这安澜秀,可以说整个姜国没有谁是不认识的,因为她的名气实在是太大太大了。姜国第一天才!十八岁...

《都市仙医武神》小说在线阅读_全文免费完结无删减 – 潇湘书院

年万字,步征万订大神作《龙皇武神》完结,以后会有第二部这期汇总一下这周起点完结的一些小说,只有十本,算是今年最少的一周。不过其中有三本是大神作品,倒是难得聚到一块了,那么简单来看看吧。1、《密教家族到...

重生之再觅良人最新章节_无弹窗全文免费阅读_笔趣阁

重生之凤医毒后看过不点赞,等于变相耍流氓嗨大家好:我是阿妍,你们的小可爱带着热乎乎的小说文案来了。今天给大家推荐的是:3本女主重生归来宠夫文!女主前世辜负良人,今生改变命运,弥补遗憾,让我来爱你,开...

饿狼老公宠太深_(茶小九)小说最新章节全文免费在线阅读下载-QQ阅读

小说:丈夫醉酒亲吻妻子,却被妻子一脚踹床下「妈,再给我半年时间。」我对着电话喊。「半年?你都混七年了!下周再没活儿,我就去接你回家放羊!」挂了电话,经纪人把综艺合同拍我面前:「客串个猎人,露个脸就行。...