首页 > 解决方案 > iFrame + PDF.js + puppeteer - 生成和显示 PDF 文件的好组合?

问题描述

从星期一开始,我尝试找到正确的方法来快速安全地生成和显示 PDF 文件,其中包含以下内容 - 也许我只是感到困惑或盲目地看到答案:

Apache - 为我的实际项目运行我的 PHP 脚本(端口 443) NodeJS - 运行单个脚本以从 HTML 生成 PDF 文件(端口 8080)

我需要什么:确保允许用户生成和查看 PDF。让查看器栏(如屏幕截图所示)可用对我来说很重要。

有一个 cookie,其中存储了 Session-Hash,并且用户在每个请求上都在其上进行身份验证(例如通过 AJAX)。

完整过程的描述:在我的项目的一页上显示了一个 iFrame。这是一个 PDF 查看器(来自 PDF.js),它周围有一些按钮: 在一切开始之前的状态

单击左侧的按钮(名为“加载 PDF 1”,...)会触发以下事件:

$(document).on("click", ".reportelement", function () {
    //some data needs to be passed
    let data = "report=birthdaylist";

     //point iFrame to a new address
     $("#pdfViewer").attr("src", "https://example.org/inc/javascript/web/viewer.html?file=https://example.org:8080?" + data);
});

此时,iFrame 将重新加载查看器,该查看器接受 GET 参数并执行它:

https://example.org/inc/javascript/web/viewer.html?file=https://example.org:8080?" + data //sends the data to the NodeJS script and recieves PDF

==> ?file=https://example.org:8080 //GET... it's bad... How to do a POST in iFrame?!

所以,看看 NodeJS Script(我不得不说我对 async 和 NodeJS 不是很熟悉):

const https = require("https");
const fs = require("fs");
const puppeteer = require('puppeteer');
const url = require("url");
var qs = require('querystring');
const request = require("request-promise");

const options = {
    key: fs.readFileSync("key.pem", "utf-8"),
    cert: fs.readFileSync("cert.pem", "utf-8"),
    passphrase: 'XXXXXXXX'
};

https.createServer(options, function (req, res) {

    (async function () {

        if (req.method == 'POST') {

            var body = '';

            req.on('data', function (data) {
                body += data;

                // Too much POST data, kill the connection!
                // 1e6 === 1 * Math.pow(10, 6) === 1 * 1000000 ~~~ 1MB
                if (body.length > 1e6)
                    req.connection.destroy();
            });

            req.on('end', function () {

                //got a selfsigned certificate only, will change it soon!
                process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0

                (async function () {

                    var result = await request.post('https://example.org/index.php', {

                            //htpasswd secured at the moment
                            'auth': {
                                'user': 'user',
                                'pass': 'pass',
                                'sendImmediately': false
                            },

                            //i would like to send the cookie oder the hash in it
                            //or something else to it ensure, that the user is allowed to
                            form: {
                                giveme: 'html'
                            }
                        },
                        function (error, response, body) {

                            //for debugging reasons
                            console.log("error: " + error);
                            console.log("response: " + response);
                            console.log("body: " + body);

                        }
                    );

                    const browser = await puppeteer.launch();

                    const main = async () => {
                        //generating pdf using result from request.post                            
                    }

                    const rendered_pdf = await main();

                    res.writeHead(200, {
                        "Access-Control-Allow-Headers": "Origin, X-Requested-With, Content-Type, Accept",
                        "Access-Control-Allow-Origin": "*",
                        'Content-Type': 'application/pdf',
                        'Content-Disposition': 'attachment; filename=mypdf.pdf',
                        'Content-Length': rendered_pdf.length
                    });

                    res.end(rendered_pdf);

                })();
            });

        } else if (req.method == 'GET') {
            console.log("we got a GET");
        } else {
            console.log("we got NOTHING");
        }

    })();

}).listen(8080);

一切正常,PDF 显示良好 - 但正如我之前提到的,我不知道如何确保允许用户生成和查看 PDF。

tldr;

有没有办法(可能没有 iFrame)来保护用户被允许?让查看器栏(如屏幕截图所示)可用对我来说很重要。

当前程序图

标签: javascriptnode.jspdfiframe

解决方案


我想我找到了解决方案。

新方法/令牌逻辑图

仅使用令牌(散列或随机字符串)来检索 PDF 文件应该这样做。

Token 不对用户进行身份验证。我认为这是一种更安全的方法?

随意评论/回答:)


推荐阅读