我在处理数据库方面不是很有经验。
我有一个 Android 应用程序,它应该向远程数据库服务器 (MySQL) 发送查询并从中获取后续结果集。
我实际上是通过以 JSON 格式向服务器发送查询来完成此操作的。服务器脚本 (PHP) 然后获取查询并执行它。然后将结果集再次解析为 JSON 并发送回 Android 应用。
我的 PHP 脚本
function run_query(mysqli $con, $query){
$res=$con->query($query);
return $res;
}
$reply = array();
if(isset($_POST['json'])) {
require_once __DIR__.'/config.php';
require_once __DIR__.'/DbController.php';
$json = json_decode($_POST['json'], true);
$query = $json['query'];
$con = (new DbController())->connect(DBNAME);
if(!$con){
$reply['suc']=false;
$reply['err_msg']=$con->error;
}
else{
$res = run_query($con, $query);
if(gettype($res)=="boolean"){
$reply['query_reply']=$res;
$reply['suc']=true;
die(json_encode($reply));
}
$i=0;
$reply['query_reply']= array();
while($row = $res->fetch_row()){
$reply['query_reply'][$i] = array();
for($j=0;$j<sizeof($row);$j++)
$reply['query_reply'][$i][$j]=$row[$j];
$i++;
}
$reply['suc']=true;
}
echo json_encode($reply);
}
如您所见,'query' 键包含由 MySQL 服务器执行的整个查询字符串。
我的问题是 - 这种方式是否包含我不知道的任何安全(或其他)漏洞?另外,有没有更好的方法来做到这一点?
我的一个项目伙伴建议我应该将查询分成不同的部分(比如 - “query_type”:“SELECT”,“table_name”:“LOGIN_TABLE”,“where_args”:“WHERE x = x”,以及依此类推)并将其发送到服务器,然后在那里重建查询并执行。
但是,我不明白这会有什么帮助。任何建议将不胜感激。提前谢谢你。
最佳答案
你的方法有很多问题。任何人都可以对您的协议(protocol)进行逆向工程,并在您的 SQL 服务器上执行他们想要的任何查询。因此,您的数据不仅可以被任何人读取,也可以被任何人修改。换句话说,您将遭到黑客攻击。
通常的做法是将蛋糕分成几层。这意味着定义一个 API,该 API 由清晰明确的方法构建,具有输入参数类型、返回值和权限。
此 API 可以以您喜欢的任何方式实现,jsonrpc、SOAP、xmlrpc,您可以选择,甚至 HTTP GET 到返回 json 的 php 脚本也可以。
最后一个选项有点笨拙,但也不错,因为它允许您使用在您网站内运行的 javascript 的相同 api。无需拥有两个相互竞争的 API。
一个例子:
API get_user_profile( user_id INT );
INPUT:用户的整数id
RETURNS:该用户的用户表中的行,取决于他们的权限。
由于 API 在经过身份验证的 session 中执行(使用 cookie 或其他),它知道是什么用户发出了请求。因此,它会让用户看到他们的电话号码/电子邮件,但不会将这些字段返回给其他用户,除非他们是管理员(这是一个简单的权限示例,当然也可能更复杂)。
因此,每个操作都需要自己的 API。有些很复杂,例如一般搜索。与其编写自己的迷你语言并使用参数来指定搜索选项,不如通过使它或多或少像网站一样来简化事情。客户端将用户在搜索字段中键入的任何内容发送到服务器(如 HTTP 表单),然后服务器决定如何处理它。
显然,如果您的 API 的任何参数直接插入到 SQL 查询中,那么 SQL 注入(inject)意味着您也会被黑客入侵。所以你需要做对,就像任何网站一样,暴露在邪恶互联网上的东西会不断受到攻击。
将客户端视为浏览器,将 API 调用视为 URL、表单、xmlhttprequest 等,将服务器视为 PHP 或任何其他服务器端语言。基本上就是这样。
关于php - 将查询从 Android 发送到远程服务器数据库的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45943120/
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru
在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo
我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr
有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳
我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b