们无法在一篇博文里解释 JavaScript 的所有细节。如果你正或多或少地涉及了 web 应用程序开发,那么,我们的 Java 工具和技术范围报告揭示了,大多数(71%)Java 开发者被归到了这一类,只是你对 JavaScript 遇到了阻碍。
毫无疑问,你已经知道了 Java 和 JavaScript,不管它们有着多么类似的命名,彼此没有共享太多共通之处。Java 的静态类型、符合直接规律的简单语法和冗长,与 JavaScript 的动态、缺乏一致性原则和怪异,有着巨大的不同。
然而,JavaScript 是 web 的编程语言,最近由于 Node.js 和 JVM 自己的 Nashorn JavaScript 引擎的发展,在服务器端获得了相当的注意。
本文,我不想只是漫谈 JavaScript 的好与不好,或重复任何人都能免费找到的、不计其数的 JavaScript 教程。我想列出一些有助于理解 JavaScript 做为一种语言的技术点,并从接近 horse的角度来理解。
我们将在本文包含下列语言级别的技术点:
另外,你会找到一些工具方面的推荐,没有这些工具,你是不想着手 JavaScript 项目的,包含了构建系统的代码质量分析和测试框架方面的工具。
优点
编写一次,差不多处处运行!
毋庸置疑 JavaScript 是 web 编程语言,是很多其它语言的编译目标,也是用来证明有时候人们只是想拥有更多自由时间的终极方式。尽管如此,这不是一件坏事。每一台能够浏览现代网站的电脑都装备了具有性能和可用的 JavaScript 引擎。最重要的是,JavaScript 代码可以在后端运行。
内置到我们喜爱的 JVM 的、轻量级高性能 JavaScript 运行时 Nashorn,完全能够解释 JavaScript 脚本,还能够解释项目中带有 Java 代码的 JavaScript 脚本。
鉴于每台电脑运行时都可获得的自由,JavaScript 成为 Java 体验的完美延续。
函数式编程:一等公民是函数,而不是递归
JavaScript 中的函数是第一类公民,它们是值,可被存储在变量里、传递给其它函数、在适当的时候再执行。
这打开了函数式编程世界的大门,这是结构化 JavaScript 编程的完美方式。
注意,JavaScript 里的对象是任何东西的映射,对象的每个特性(attribute)都在同一个映射里:函数、属性(property)、构造器;易变性带来了更大的隐患,而对于 Java,你至少能够确保方法和字段结构在某种程度上是稳定的。
反过来,这使得函数式编程更加有利:涉及到小的、可理解函数和不变的数据结构是在 JavaScript 里运行的方式。
这不是没有依据的,下面是在 JavaScript 里定义一个 reduce 函数的例子,来自于《Eloquent JavaScript》一书。
function forEach (array, action) { for (var i = 0; i < array.length; i++) { action (array[i]); //apply action to every element of the arra. } } function reduce (combine, base, array) { forEach (array, function (element) { base = combine (base, element); // and here we apply function passed as ‘combine’ parameter to ‘base’ and ‘element’ }); return base; } function add (a, b) { // btw, this is how you define a function in JavaScript return a + b; } function sum (numbers) { return reduce (add, 0, numbers); }
注意:我们没有在这里使用 reduce 的递归版本。JavaScript 没有以尾调用【注1】为特色,这意味着每个函数的递归版本都将用到栈的深度,和 Java 一样,如果你递归太深,程序就崩溃。
继承:就像真实的世界
JavaScript 的继承是基于原型的。即,你没有扩展了其它类型的类型,而实际上,你拥有的实例从其它实例继承了功能。
想象一下,对象A就像一个映射,我们刚才稍微提到了一些、但是用了不同的视角,然后另一个类似映射的对象B从A继承了一切。
这说明B可以访问A所有部分:A的方法、字段等等。
在实践中,我从来没有看到有人实际使用简单的基于原型的继承。通常当某人需要继承时,他只是构造类,因此你可以用到所有广泛的技能,和基于类的继承的工作模式。
——Rene Saarsoo,XRebel 前端工程师
我不太确定 Java 开发者应该从中吸取什么,但是要当心继承方式的不同,对于父级对象要格外留意、而不要意外地改变整个程序的行为。
任何时候要避免的
列出不可靠的 JavaScript 设计上的决定比想象中要容易。在 JavaScript 程序中要避免的最明显的地方就是全局变量的声明。
注意,在 JavaScript 里,无论什么时候,不使用 var 关键词定义变量,那么定义的变量被推到了它们被定义的作用域顶端。这意味着,每个用这种方式定义的变量将跑到全局范围顶部,这会引发冲突以及你和同事不可预期的头痛。
可以开启 strict 模式。只需在脚本文件顶部写上“use strict”,那么不经意编写的全局变量声明将显示错误。
JavaScript 与 Java 另一个重要的不同点在于,前者是动态类型语言,其真谛是所有东西都可以是任何类型。这很明显了,实在不能再强调了:不要针对不同类型的值,去复用相同的变量。
跟踪刚开始是个 string 类型的变量,但是现在它成了浮点数、或者函数了,相信我!
还有,我不想太深入类型和布尔值的讨论,但是要警惕 JavaScript 引擎扔给你的隐式类型转换。
搞定工作的小提示
正如我上面提到的,在编程上要更加注意这种语言的语法和怪癖,而不仅仅是知道。项目很少由于语言的不足而失败,更多的失败是与总体项目框架不足有关。下面是有助于你交付项目的一些工具。
静态代码分析
大部分项目是不同的,其复杂度和需求导致了大量的细节,你该如何着手代码库呢。尽管如此,在所有地方都有一致性的目标,那就是代码质量。
是的,代码质量,对于任何开发者来说,最重要的工作就是交付。但是不要在质量上妥协,不要对你提交的代码感到不自信就不情愿与同事分享。
幸运的是,JavaScript 有一套得体的解决方案——JSHint。JSHint 是为 JavaScript 量身打造的静态分析工具,与应用于 Java 代码的 FindBug 类似。JSHint 可以在你的代码库运行,并高亮出可疑的或有问题的地方,即使你不会马上产生 bug,但这些地方将来变得难以维护。在项目中支持它相当简单。帮自己一个忙——如果你在写 JavaScript 代码,就用 JSHint 让它更安全、少一些尴尬。
REPL
REPL 代表“读取-求值-输出”循环(Read-Eval-Print Loop)【注2】,是很多动态语言的强大工具。如果你看过 Scala 或 Groovy,你一定能够理解这个概念。
激活 JavaScript REPL 的一种途径是打开浏览器的控制台,它产生了对 JavaScript 代码求值的界面。
另一个比较方便的工具是 jjs,它捆绑在 JDK1.8。
它是命令行工具,允许你访问 JDK 中的 Nashorn JavaScript 引擎,完全有能力执行那些甚至最为严格的 JavaScript 脚本。
测试
对于任何一个项目,你都想运行一些测试。测试对于动态类型的语言尤为重要,最好选择一种测试框架。我推荐 Jasmine,它是用于测试 JavaScript 的行为驱动开发框架。
在 Jasmine,你用 describe 描述测试套件,它阻止了你想测试的代码访问。在测试中的代码完成后,你 expect 一些结果。
很明显这里不是要给出教程,但是我想让你一瞥 JavaScript 代码看起来是多么地优雅。Jasmine 是 JavaScript 项目最好的实践之一,我们私下在产品开发中应用到了 ZeroTurnaround 项目,尤其是对于富含 JavaScript 的不间断运行的交互分析器 XRebel。
构建工具
最后,你的项目将需要的、比较重要的是构建工具。如果你在 Java 项目中使用 JavaScript,请确保你可以避开 Java 构建工具,这就差不多足够了。但是,对于独立的 JavaScript 项目,没有必要引入庞然大物—Maven【注3】。
可以考虑的 JavaScript 项目用到的构建工具是 GulpJS【注4】。它是基于插件的构建系统,你可以为其指定任务。任务可以是“拷贝 src 目录下的 .js 文件到 dest”、或“压缩我的 JavaScript 代码用于生产环境”。让人受到震动的是,GulpJS 把任务相关的文件流加入过滤器,因此你可以把上面的两个任务加入一次有效的清扫中。
还有大量的可用插件,借助适当的构建系统,你将发现项目中的协作会轻松很多。
结论
我们只是看到了 JavaScript 的冰山一角,并尽量介绍一些 Java 开发者在解决 JavaScript 时应该知道的概念和工具。自然地,这里没有提供要学习的完整的技术清单,但是如果你正准备义无反顾地深入 JavaScript 项目,这会帮助你起步,拥抱 JavaScript 的怪癖将有助于你不会频繁地沮丧。
你了解让 JS 开发者走向快乐的秘密或最佳实践吗?毫无疑问应该去分享!在下面评论或在 Twitter:@shelajev 上与我交谈。我乐于听到你的想法!
作者:前端小攻略
原文:https://my.oschina.net/u/3972188/blog/2999914
略。基本可以从wikipedia上找到解释。
http://kylin.incubator.apache.org/docs/gettingstarted/terminology.html
在介绍Kylin的各种操作之前,首先让我们来了解一下Kylin的总体设计,包括其架构、工作流程、和数据模型。
Kylin目前是一个MOLAP系统,也就是基于对Cube进行预计算来满足低延迟的查询处理。Kylin的数据源就是Hive上的表,以星型模式存在。Kylin的离线计算过程(下图中蓝色箭头的数据流)会读取Hive中的原始数据,将事实表和维表join起来,然后对各种维度组合(cuboid)进行计算。计算后的cube以key-value的形式存储在HBase中。
对于SQL请求,Kylin的查询引擎会判断SQL能否由HBase中的cube满足。如果可以,查询就会转换为HBase的range scan操作,直接获得结果数据,因此能做到秒级的响应。对于无法由cube实现的查询,Kylin可以将查询路由给Hive执行,不过当前版本由于性能原因,disable了路由查询的功能。
使用Kylin的工作流程如下图所示。
首先,RD创建一个Kylin的项目。一个项目中可以定义多个Cube。
然后,RD需要告诉Kylin需要访问Hive上的哪些表,即「加载Hive表」。注意这里Kylin只会从Hive Metastore同步表的元信息,并不会读取表的数据。
之后就是最主要的「Cube建模」过程。这一步就是定义Cube的元信息,包括Data Model(指定事实表与维表,以及他们的连接方式)和Cube Model(有哪些维度和度量,如何增量刷新,以及聚集组和rowkey这些高级设置)。
建模完成之后,RD就可以出发「Cube构建」的动作了。Kylin提供了Cube构建管理的REST API,因此Cube的构建是可以与现有的调度系统集成的。
Cube构建成功之后,数据分析师就可以进行查询啦,例如进行常见的上卷下钻操作。下一小节会提到,Kylin中的Cube对分析师是透明的,分析师还是对Hive中的星型模式查询,这是Kylin区别于其他方案(例如生产aggr表和summary表)的主要特征。
在Kylin系统内,不同角色人员看到的数据模型是不同的。下图说明了其中的区别。
关于Cube建模的步骤和操作方式,目前官方教程已经比较全面了,故不再赘述。请读者自行阅读。
http://kylin.incubator.apache.org/docs/tutorial/create_cube.html
.本文为公测版,一旦发现有任何错误内容,会立即进行修复,请持续关注本站。
2.本文在正式版之前会不断的邀请各路黑客大手进行评价测试,欢迎提出异议。
本文仅针对网站部分,本文会对typecho,wordpress进行测试
如果你root端口为22,并且密码是123456,就没必要往下看了。
网站环境为linux tengine/nginx mariaDB,同理,apache也有相关设置,百度实验下即可。
**本文会阐述以下部分
1.基础权限控制
2.执行目录限制
3.PHP的限制
4.webshell写入与执行
5.权限细分,必须写入的目录**
1.基础权限控制
什么叫基础权限?在LNMP架构下,nginx+php-fpm架构需要什么权限?
这里我们先来看一下默认权限
默认我们的nginx运行用户是nginx,而php-fpm的默认用户是apache,默认用户安全吗?
看一下webshell
uid=48(apache) gid=48(apache) groups=48(apache)
很明显,我们的默认用户是apache
我们使用shell新建一个目录,很明显,我们是无法建立文件夹的
mkdir: cannot create directory `1': Permission denied
在网上很多教程会告诉我们,吧nginx和phpfpm改成同样的用户,我们看看会发生什么。
[root@gov 1]# sudo -u nginx mkdir 1
[root@gov 1]# ll
total 4
drwxr-xr-x 2 nginx nginx 4096 Aug 19 18:08 1
没错,这是一项愚蠢的决定!
所以默认权限是安全的吗?并不是,你忘了上传目录,我们看下上传目录的权限
drwxrwx--- 3 nginx apache 4096 Aug 14 17:09 uploads
没错,上传目录的存在就是放大权限,如果php没有写入权限,那么他就无法上传图片。
假设,我们手里有一个0day,现在我要用它来getshell
我会选择uploads目录
-rw-r--r-- 1 apache apache 0 Aug 19 18:11 1.php
完美写入,接着你的站就会被玩坏了,写入shell后我们可以插件数据库链接密码,进网站后台,脱裤,挂黑链等等等等
网站里有几个目录是默认可以写入的?在你的网站目录下执行ls -l
通常plugins themes uploads
这三个目录都是可以写入的。
你还有其他目录可以写入?赶紧修改权限吧!
加入我们的网站在/var/www/html/root
那么下面的命令是极好的,对于必须要有上传权限的uploads目录,我们下面再说
chown -R nginx.apache html
find /var/www/html/root -type d -exec chmod 750 {} \;
find /var/www/html/root -not -type d -exec chmod 640 {} \;
chmod 770 /var/www/html/root/uploads -R
如果你有某些插件也需要写入权限,给他权限,并认真看下面的内容。
2.执行目录限制
我们的apache权限有多大呢?相同的网站拥有相同的权限。
默认情况下,我们的apache权限能浏览大部分目录。最要命的问题在于,他可以跨站执行,从你的网站一直接执行到网站二。
我们需要给他一个限制,每个虚拟主机一个单独的限制,没错就是open_basedir。
这里我们需要特别的技巧,每个虚拟机都要限制
这样虚拟主机将只允许在网站目录和tmp目录执行,而不能穿越到其他目录
在乌云有一篇讨论绕过open_basedir
的文章,所以open_basedir
只能让你更安全而不是彻底安全,所以你还需要往下看。
server {
location ~ .*\.php(\/.*)*$ {
#include pathinfo.conf;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param PHP_VALUE "open_basedir=$document_root:/tmp/";
3.PHP的限制
我们想一个另类解决办法,如何限制webshell的执行?
在php.ini里,我们可以选择关闭某些不安全的函数
但是由于php这玩意分之多又复杂,这里只能整理出一部分不安全的函数。
直接添加到php.ini最后面即可
disable_functions=exec,system,passthru,shell_exec,escapeshellarg,escapeshellcmd,proc_close,proc_open,ini_alter,dl,popen,pcntl_exec,socket_accept,socket_bind,socket_clear_error,socket_close,socket_connect,socket_create_listen,socket_create_pair,socket_create,socket_get_option,socket_getpeername,socket_getsockname,socket_last_error,socket_listen,socket_read,socket_recv,socket_recvfrom,socket_select,socket_send,socket_sendto,socket_set_block,socket_set_nonblock,socket_set_option,socket_shutdown,socket_strerror,socket_write,stream_socket_server,disk_total_space,disk_free_space,diskfreespace,getrusage,get_current_user,getmyuid,getmypid,dl,leak,listen,chgrp,link,symlink,dlopen,proc_nice,proc_get_stats,proc_terminate,shell_exec,sh2_exec,posix_getpwuid,posix_getgrgid,posix_kill,ini_restore,mkfifo,dbmopen,dbase_open,filepro,filepro_rowcount,posix_mkfifo,putenv,sleep,chmod,chown,chroot,ini_set,phpinfo,proc_get_status,error_log,syslog,readlink,putenv
在看webshell,我们会发现里面空空如也了,并不能执行命令了。
4.webshell写入与执行
现在我们的网站已经很安全了,他能否更加安全?
现在,我们就要说说我们必须要有执行权限的upload目录了,nginx同样提供了解决方案
location ~ /(usr/uploads)/.*\.(php|php5)?$
{
deny all;
}
这个时候我们打开uploads中的php文件会提示403
403 Forbidden
You don't have permission to access the URL on this server. Sorry for the inconvenience.
我们的效果得到验证,即使写入也不能执行。
5.必须要写入权限但是又包含php文件的目录。
例如我的用的邮件通知插件目录内有cache和和log目录,是必须有写入权限的
这里千万不要犯懒,直接给CommentToMail
写入
location ~ /(usr/uploads|usr/plugins/CommentToMail/cache|usr/plugins/CommentToMail/log)/.*\.(php|php5)?$
{
deny all;
}
既可以实现写入文件,又可以让php无法执行。
总结,上面的所有配置:
用户与PHP运行权限分离
nginx:apache
执行目录限制
open_basedir
PHP函数限制
php.ini
特殊目录关闭PHP解析
deny all
权限细分
xx|xx|xx
欢迎拍砖,同时 起司靶场v2 上线,完全脱离安全锁之类的软件,欢迎测试。
起司靶场v2
*请认真填写需求信息,我们会在24小时内与您取得联系。