65.9K
CodeProject 正在变化。 阅读更多。
Home

解决客户端计算机上的 Web 安全限制

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.71/5 (5投票s)

2016年8月19日

CPOL

2分钟阅读

viewsIcon

9900

downloadIcon

182

PHP 和 C# 通过 thrift 框架协同工作

引言

这个示例允许你在内网 Web 环境中,在客户端机器上执行命令、打开文件等。

 

背景

一些时间以前,我正在开发一个用于控制建筑项目开发的应用程序,我的客户要求它必须是一个 Web 应用程序。其中一个挑战是,在这个 Web 应用程序中应该能够通过点击网页上的链接来打开图纸和文档。正如我们所知,出于安全原因,这是不可能的,所以我决定使用桌面支持软件来在客户端机器上执行这些任务。而内网 Web 应用程序和桌面软件之间的桥梁是由 THRIFT (一种接口定义语言和二进制通信协议) 实现的。

使用应用程序

 

注意:你必须运行 composer 来获取 symfony 中的 vendors ....

我创建了两个示例项目:一个是充当 thrift 客户端的 Symfony 2.8 Web 应用程序,另一个是在客户端机器上运行的 C# 应用程序,作为服务器。一切都从编写一个 .thrift 文件开始,该文件是由 thrift 类型和服务组成的接口定义,如下所示

namespace csharp ThriftServer
namespace php ThriftSampleBundle.Util
struct FileInf
{
  1: string FileName,
  2: string extension,
  3: bool isDir
}
service OpenFileService{
    bool openFile (1:FileInf info,2:string parameters),
    list <FileInf> listFolder(1:string path),
}

这里有两个方法的定义,一个用于列出指定路径中的文件夹和文件,另一个用于运行或打开特定文件,所有这些都在客户端机器上进行。然后运行 thrift 命令来生成客户端和服务器代码。

通用语法是

thrift --gen <language> <Thrift filename

对于 PHP

thrift --gen php OpenFileService.thrift

对于 C#

thrift --gen csharp OpenFileService.thrift

因此,你必须在服务器上实现这两个方法,并通过 RPC 从客户端调用它们。

一些来自 PHP 的代码,充当客户端,请注意我使用 "$this->request->getClientIp()" 来获取内网客户端 IP 并知道连接到哪里。因此,如果 Web 浏览器有代理配置,你必须指定不为该站点使用代理,否则它会获取错误的 IP 地址。

private function openConnection() {
        
            // Create a thrift connection (Boiler plate)
            $socket = new TSocket($this->request->getClientIp(), '9090');

            $this->transport = new TBufferedTransport($socket);
            $protocol = new TBinaryProtocol($this->transport);

            // Create a calculator client
            $this->client = new OpenFileServiceClient($protocol);

            // Open up the connection
            $this->transport->open();        
    }

要从 PHP 客户端调用 C# 服务器上的 listFolder($path) 方法

public function listFolder($path) {
        try {
            $this->openConnection();
            // Perform operation on the server
            $result=$this->client->listFolder($path);
           
            // And finally, we close the thrift connection
            $this->transport->close();
            return $result;
        } 

        catch (\Exception $tx) {
            // a general thrift exception, like no such server
            echo "ThriftException: ".$tx->getMessage()."\r\n";
        }
    }

要从 PHP 客户端调用 C# 服务器上的 openFile($path,$extension) 方法

public function openFile($path,$extension) {
        try {
            $this->openConnection();


            $fileInfo=new FileInf();
                $fileInfo->FileName=$path;
                $fileInfo->extension=$extension;
            // Perform operation on the server
            $this->client->openFile($fileInfo,null);

            // And finally, we close the thrift connection
            $this->transport->close();
        } 

        catch (\Exception $tx) {
            // a general thrift exception, like no such server
            echo "ThriftException: ".$tx->getMessage()."\r\n";
        }
    }

现在让我们看看如何在 C# 中启动服务器端

private void thrift(){
            //Thrift stuff
            var handler = new OpenFileHandler();
            var processor = new OpenFileService.Processor(handler);
            
            TServerTransport transport = new TServerSocket(9090);
            TServer server = new TThreadPoolServer(processor, transport);
            
            server.Serve();
            //end thrift
        }

以及服务处理程序实现

/*
 * Created by SharpDevelop.
 * User: lca85
 * Date: 8/16/2016
 * Time: 1:09 PM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;

namespace ThriftServer
{
    /// <summary>
    /// Description of OpenFileHandler.
    /// </summary>
    public class OpenFileHandler:OpenFileService.Iface
    {
        public FileInf fileToOpen;
        public OpenFileHandler()
        {
        }               
        
        public bool openFile(FileInf info, string parameters)
        {            
            System.Diagnostics.Process.Start(info.FileName);
            return true;
        }
        
        public IAsyncResult Begin_openFile(AsyncCallback callback, 
                                           object state, FileInf info, string parameters)
        {
            throw new NotImplementedException();
        }
        
        public bool End_openFile(IAsyncResult asyncResult)
        {
            throw new NotImplementedException();
        }
        
        public List<FileInf> listFolder(string path)
        {
            DirectoryInfo di=new DirectoryInfo(path);
            FileInfo[] files=di.GetFiles();
            DirectoryInfo[] directories=di.GetDirectories();
            List<FileInf>aux_list=new List<FileInf>();
            foreach (DirectoryInfo element in directories) {
                FileInf aux_file=new FileInf();
                aux_file.FileName=element.FullName;
                aux_file.Extension="";
                aux_file.IsDir=true;
                aux_list.Add(aux_file);
            }
            foreach (FileInfo element in files) {
                FileInf aux_file=new FileInf();
                aux_file.FileName=element.FullName;
                aux_file.Extension=element.Extension.Replace(".","");
                aux_file.IsDir=false;
                aux_list.Add(aux_file);
            }
            return aux_list;
        }
        
        public IAsyncResult Begin_listFolder(AsyncCallback callback, object state, string path)
        {
            throw new NotImplementedException();
        }
        
        public List<FileInf> End_listFolder(IAsyncResult asyncResult)
        {
            throw new NotImplementedException();
        }
    }
}
© . All rights reserved.