2009年8月21日
防盗链原理:
http标准协议中有专门的字段记录referer
一来可以追溯上一个入站地址是什么
二来对于资源文件,可以跟踪到包含显示他的网页地址是什么。
因此所有防盗链方法都是基于这个Referer字段
网上比较多的2种
一种是使用apache文件FileMatch限制,在httpd.conf中增加 ( 其实也可以将把下面的语句存成一个.htaccess文件),并放到你的网站的根目录(就是www/html目录),这样子别人就没有办法盗连你的东东了~~
SetEnvIfNoCase Referer "^http://yahoo.com/" local_ref=1
Order Allow,Deny
Allow from env=local_ref
Allow from 127.0.0.1
这种很方便禁止非允许访问URL引用各种资源文件
请大家注意,把第一句"^http://yahoo.com/"改为你的网站,比如我的网站是: http://www.linji.cn
我应该这么写的
"^http://www.linji.cn/"
第二种是使用rewrite,需要增加apache的mode_rewrite,支持.htaccess文件目录权限限制
在虚拟主机根目录增加.htaccess文件,描述从定向,把非本地地址refer的图片文件都从定向到警告图片或者警告网页上。
首先要确认你的服务器或空间的服务器解译引擎为Apache2,还有支持.htaccess客户设置文件,
如果你有自己的服务器就请先对./conf/httpd.conf 文件做以下修改
找到:#LoadModule rewrite_module modules/mod_rewrite.so
把前面的 # 给去丢
找到等一个 AllowOverride None 改为 AllowOverride All
重启Apache2服务器
接下就是做一个 .htaccess 文件了,其 .htaccess 文件内容为
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^http://aaoo.net/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^http://aaoo.net$ [NC]
RewriteCond %{HTTP_REFERER} !^http://www.aaoo.net/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^http://www.aaoo.net$ [NC]
RewriteRule .*.(jpg|jpeg|gif|png|bmp|rar|zip|exe)$ http://down.yoyo.com.ru/err.html [R,NC]
其中有色的地方都是要改为你的:
红色:就是改为你提供下载页面的地址,也就是只有通过这个地址才可以下载你所提供的东东。
蓝色:就是要保护文件的扩展名(以|分开),也就是说以这些为扩展名的文件只有通过红色的地址才可以访问。
绿色:如果不是通过红色的地址访问蓝色这些为扩展名的文件时就回重定向到绿色地址上。
这个方法有个好处是,不同的虚拟主机用不同的描述定义。
接下就是怎么用 .htaccess 文件来实现防盗链了。
首先要在空间上建两个目录(当然目录名随你),一个为 web 另一个为 down ,
web 是用来放下载页面的(或下载程序),down 当然就是放你提供的东东的啦,
把 .htaccess 文件的红色部分改一下,改为http://你的域名/web。蓝色部分
改为你要保护文件的扩展名。绿色部分改为http://你的域名/web。改后保存
.htaccess 文件把它上传到 down 目录。
还有第三种:
我在解决plog禁止盗链的时候,发现个问题,也算个好方法。
plog把所有资源都自己管理起来,用resserver.php来动态显示,这样统一的入口方便添加权限操作。
同时造成上面2种方法无法使用,因为不再是apache直接访问资源文件,而是php通过文件读取。
因此只能在代码中做手脚:在读取资源文件输出之前,加如下判断代码
引用
$referer = $_SERVER['HTTP_REFERER'];
$selfurl = $_SERVER['HTTP_HOST'];
if(false == strpos($referer,$selfurl))
{
echo '非法盗链!';
exit(1);
}
这里有些偷懒,直接看引用地址中是否包含host地址,不过原理就是这样,判断referer是否是本站地址。
我们常常在下载的时候,也碰到盗链网站无法下载,报盗链的问题。要下载这类文件最简单的方法就是改referer
比方flashget中,网址下面的"引用"一栏中,直接填写下载地址就可以了。
--------------------------
09博客园纪念T恤新闻:
微软:不一样的PowerPoint 2010网站导航:
博客园首页 个人主页 新闻 社区 博问 闪存 找找看文章来源:
http://www.cnblogs.com/xiaoao808/archive/2009/08/21/1551756.html
posted @
2009-08-21 23:30 破名超难起 阅读(326) |
评论 (0) |
编辑 收藏
2009年8月4日
这两天完善了一下视频转换这个东西,以前做的那套东西上传完之后就开始转换,无法适应大并发量下的视频转换(我觉得同时有10个ffmpeg进程在转视频服务器肯定要挂掉),所以我用了另一套方案,视频上传之后先不转换,把视频的基本信息存到数据库中,然后由程序定时的从数据库中读取数据,依次转换视频。具体做法是:1、上传文件,将文件名存入数据库,同时在数据库标明videostat字段为0(表示未转换)
2、通过程序,每隔30秒(根据不同情况可以改变)取出一个未转换(videostat=0)且失败次数小于5(confailtime<5)的纪录
3、开始转换视频,这里要先将数据库中videostat字段改为2(表示正在转换)不然30秒钟转换不完下个进程又会读到这条纪录开始转换......
4、等待转换进程结束,如果成功将相应纪录的videostat字段的值改为1(表示转换成功),若转换失败则将失败次数字段加一(confailtime=confailtime+1)
在鼓捣这东西的过程中,遇到了一个问题,如果一个进程先执行p.waitFor();方法而后输出命令行中的结果是不行的,即:
Code
int flag = p.waitFor();
InputStream inErr = p.getErrorStream();
InputStream inIns = p.getInputStream();
BufferedReader brErr = new BufferedReader(new InputStreamReader(
inErr));
BufferedReader brIns = new BufferedReader(new InputStreamReader(
inIns));
// inErr读取输出信息开始
String strsErr = "";
String strErr = brErr.readLine();
while (strErr != null) {
strsErr = strsErr + strErr + "\n";
System.out.println(strErr);
strErr = brErr.readLine();
}
// inErr读取输出信息结束
// inIns读取输出信息开始
String strsIns = "";
String strIns = brIns.readLine();
while (strIns != null) {
strsIns = strsIns + strIns + "\n";
System.out.println(strIns);
strIns = brErr.readLine();
}
如果这样执行的话进程会挂起,无法继续下午,而正确的方法是先读取命令行的数据,再来waitFor();
还有一点需要注意的是获得命令行的输出结果先要从错误流中获得,即(ErrorStream),而非从输入流(InputStream)中获得,很有用的经验。
--------------------------
09博客园纪念T恤新闻:
自由软件基金会列举Windows 7之七宗罪网站导航:
博客园首页 个人主页 新闻 社区 博问 闪存 找找看文章来源:
http://www.cnblogs.com/xiaoao808/archive/2009/08/04/1538824.html
posted @
2009-08-04 17:45 破名超难起 阅读(265) |
评论 (0) |
编辑 收藏
2009年8月3日
很久不在这里发帖子了,最近在家闲来无事,想到转视频的那东西又要做了,遂翻出以前的帖子,看到一年前丰哥让我做一下文件上传的进度条....额~~那就做一下吧。
东西很简单,主要用到commons-fileupload,其中有一个progressListener的接口,该接口可以实现实时更新已上传文件的大小,有了这个还说什么呢?
给出代码
代码
package lc.progress;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import lc.progress.vo.fileUploadStatus;
import org.apache.commons.fileupload.ProgressListener;
public class myProgressListener implements ProgressListener {
private HttpSession session;
public myProgressListener(HttpServletRequest req) {
session=req.getSession();
fileUploadStatus status = new fileUploadStatus();
session.setAttribute("status", status);
}
/* pBytesRead 到目前为止读取文件的比特数
* pContentLength 文件总大小
* pItems 目前正在读取第几个文件
* 只要在session中实时保存文件上传的状态(这里我用fileUploadStatus类来封装)
*/
public void update(long pBytesRead, long pContentLength, int pItems) {
// TODO Auto-generated method stub
fileUploadStatus status = (fileUploadStatus) session.getAttribute("status");
status.setPBytesRead(pBytesRead);
status.setPContentLength(pContentLength);
status.setPItems(pItems);
}
}
然后在上传得servlet或action中加入这样一段代码,就可以把自定义的progressListener添加进去
代码
myProgressListener getBarListener = new myProgressListener(req);
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setProgressListener(getBarListener);
最后就是通过js来不断的访问另一个servlet来实时返回上传状态就可以了,限于篇幅我就不再贴代码了,有兴趣的读者可以自己下载来看。
代码下载(目标另存为就行了)
--------------------------
09博客园纪念T恤新闻:
网速调查报告:韩国互联网网速全球居首网站导航:
博客园首页 个人主页 新闻 社区 博问 闪存 找找看文章来源:
http://www.cnblogs.com/xiaoao808/archive/2009/08/03/1537870.html
posted @
2009-08-03 19:46 破名超难起 阅读(4886) |
评论 (7) |
编辑 收藏
2009年5月20日
package lc.util;
import java.math.BigDecimal;
public class MathHelper {
private static final int DEF_DIV_SCALE = 10;
private MathHelper() {
}
/**
* 提供精确的加法运算。
*
* @param v1
* 被加数
* @param v2
* 加数
* @return 两个参数的和
*/
public static double add(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
}
/**
* 提供精确的减法运算。
*
* @param v1
* 被减数
* @param v2
* 减数
* @return 两个参数的差
*/
public static double sub(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2).doubleValue();
}
/**
* 提供精确的乘法运算。
*
* @param v1
* 被乘数
* @param v2
* 乘数
* @return 两个参数的积
*/
public static double mul(double v1, double v2) {
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2).doubleValue();
}
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 小数点以后10位,以后的数字四舍五入。
*
* @param v1
* 被除数
* @param v2
* 除数
* @return 两个参数的商
*/
public static double div(double v1, double v2) {
return div(v1, v2, DEF_DIV_SCALE);
}
/**
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 定精度,以后的数字四舍五入。
*
* @param v1
* 被除数
* @param v2
* 除数
* @param scale
* 表示表示需要精确到小数点以后几位。
* @return 两个参数的商
*/
public static double div(double v1, double v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 提供精确的小数位四舍五入处理。
*
* @param v
* 需要四舍五入的数字
* @param scale
* 小数点后保留几位
* @return 四舍五入后的结果
*/
public static double round(double v, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b = new BigDecimal(Double.toString(v));
BigDecimal one = new BigDecimal("1");
return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
}
--------------------------
09博客园纪念T恤新闻:
王建宙台湾布道TD:痛快,一起努力的感觉网站导航:
博客园首页 个人主页 新闻 社区 博问 闪存 找找看文章来源:
http://www.cnblogs.com/xiaoao808/archive/2009/05/20/1469589.html
posted @
2009-05-20 17:13 破名超难起 阅读(305) |
评论 (0) |
编辑 收藏
2008年9月22日
最近搞的一个通讯录想要加一个Ajax的自动完成功能,看起来功能虽小,可给用户的体验会改进不少。在一个介绍了几十种java的Ajax框架的网页里面,我找到了AjaxTags这个小东西,开始了我的第一次Ajax之旅。
从AjaxTags的官方网站上面http://ajaxtags.sourceforge.net/可以下载到其最新的版本,目前是AjaxTags1.3顺便下载了一个官方的小例子看了看,确实很好阿,例子中使用Ajax完成了11种功能,然而我需要的是自动完成(autocomplete)部分的代码,所以重点研究这一部分
jsp页面中,首先当然是要添加AjaxTags的标签支持,需要如下语句
Code
<%@ taglib uri="http://ajaxtags.org/tags/ajax" prefix="ajax"%>
然后在页面中加入如下的标签
Code
<ajax:autocomplete
source="model"//从控件"model"中获得输入的字符
target="make"//通过Ajax自动完成控件"make"的内容
baseUrl="${contextPath}/autocomplete.view"//Ajax执行时调用的请求路径
className="autocomplete"//css类名
indicator="indicator"
minimumCharacters="1"//Ajax执行需要输入的最小字符数
/>
在官方的例子中使用的是Servlet来完成Ajax,而对于使用struts就不适用了,后面说这个问题。
在 autocomplete.view对应的Servlet类中需要建立xml来供页面调取,代码如下
Code
public class AutocompleteServlet extends BaseAjaxServlet {
public String getXmlContent(HttpServletRequest request, HttpServletResponse response)
throws Exception {
String model = request.getParameter("model");//从页面获取控件"model"的输入值
CarService service = new CarService();
List<Car> list = service.getModelsByName(model);//调用CarService的方法获得汽车的List
// Create xml schema
return new AjaxXmlBuilder().addItems(list, "model", "make",true).toString();//生成xml
}
}
其实还是很简单的,接下来看CarService的代码吧,重点其实只有一段,然后在下面显示出自动提示,于是可以把刚才的那个ajax标签修改如下
Code
public class CarService {
private static List<Car> cars = new ArrayList<Car>();
static {
cars.add(new Car("Ford", "Escape"));
cars.add(new Car("Ford", "Expedition"));
cars.add(new Car("Ford", "Explorer"));
cars.add(new Car("Ford", "Focus"));
cars.add(new Car("Ford", "Mustang"));
cars.add(new Car("Ford", "Thunderbird"));
cars.add(new Car("Honda", "Accord"));
cars.add(new Car("Honda", "Civic"));
cars.add(new Car("Honda", "Element"));
cars.add(new Car("Honda", "Ridgeline"));
cars.add(new Car("Mazda", "Mazda 3"));
cars.add(new Car("Mazda", "Mazda 6"));
cars.add(new Car("Mazda", "RX-8"));
}//其实把上面这个地方改为数据库查询就可以从数据库中得到List来供页面显示
public CarService() {
super();
}
public List<Car> getModelsByMake(String make) {
.
}
public List<Car> getModelsByName(String name) {
..
}
public List<Car> getAllCars() {
return cars;
}
}
例子看完了,开始实际操作吧,在我的页面中,需要通过一个名为"name"的文本框输入要查询的人的姓名
Code
<ajax:autocomplete
source="name"
target="name"
baseUrl="ajaxfinduser.do"
className="autocomplete"
indicator="indicator"
minimumCharacters="1"
/>
接下来是我的Action,在写Action的时候,我以为只需要把原来Servlet继承的BaseAjaxServlet改为BaseAjaxAction就可以了,可后来才发现,jar包中根本就没有BaseAjaxAction这个类,无语,去官方网站上看了后才知道,在1.2更新到1.3的时候,把对Struts的支持去掉了,如果想支持Struts的话需要建立自己的BaseAjaxAction
(Struts removed, to use it create your own BaseAjaxAction.java and implement BaseAjaxXmlAction then just call xml = AjaxActionHelper.invoke(this, request, response);)
下载了一份AjaxTags的源码来看,原来AjaxActionHelper.invoke();这个方法需要调用Action中的getXmlContent方法来完成xml的写入,那就好说了,代码如下:
Code
package com.txl.action;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.ajaxtags.servlets.BaseAjaxXmlAction;
import org.ajaxtags.xml.AjaxXmlBuilder;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.ajaxtags.servlets.AjaxActionHelper;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.txl.service.AjaxFindUserService;
import com.vo.User;
public class AjaxFindUserAction extends Action implements BaseAjaxXmlAction {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws IOException, Exception {
response.setCharacterEncoding("utf-8");
response.getOutputStream().print(new String(AjaxActionHelper.invoke(this, request, response).getBytes("UTF-8"),"ISO-8859-1"));//这里需要转换编码,不然无法支持中文查询
response.getOutputStream().flush();
return null;
}
public String getXmlContent(HttpServletRequest request,
HttpServletResponse response) throws Exception {
String realname = request.getParameter("name");
ApplicationContext ctx = WebApplicationContextUtils
.getRequiredWebApplicationContext(servlet.getServletContext());//用ssh时需要在这里引入spring的配置文件,不然会在调用dao的时候报空指针异常
AjaxFindUserService service = (AjaxFindUserService) ctx
.getBean("AjaxFindUserService");
List<User> list = service.getUsersByRealname(realname);
return new AjaxXmlBuilder()
.addItems(list, "realname", "realname", true).toString();
}
}
剩下工作就是在struts-config.xml中配置对应的action,在spring中配置对应的bean就ok拉
--------------------------
09博客园纪念T恤新闻:
Office 2010双拳出击加强反盗版网站导航:
博客园首页 个人主页 新闻 社区 博问 闪存 找找看文章来源:
http://www.cnblogs.com/xiaoao808/archive/2008/09/22/1295661.html
posted @
2008-09-22 09:42 破名超难起 阅读(200) |
评论 (0) |
编辑 收藏
2008年8月21日
我一直有通宵下东西的习惯,可又不忍心让笔记本下载完成后一直等到我睡醒,所以我经常用迅雷给我们提供的下载完成后自动关机这个功能。
然而现在迅雷运行在了虚拟机里面,这就郁闷了,即使自动关机也只能关掉一个虚拟机的进程,无奈我想到可不可以用shell程序来监测虚拟机的进程,当他关闭后就运行关机的命令,经过测试,果然成功了,具体代码如下:
Code
#!/bin/bash
while [ `pidof -s $1` ]
do
sleep 2 #&& echo "ok"
done
date
echo "Done..shuting down in 60 seconds." && sleep 60
shutdown -h -P now
将代码保存在shutdown.sh文件中
使用起来也很方便,用"ps ux"找到vbox运行的进程,将其对应的time command值作为参数输入进来,例如我的是:
lichao 10659 91.7 52.0 1224284 1079860 ? Sl 21:49 11:01 /opt/VirtualBox-1.6.4/VirtualBox -comment winxp -startvm 5e04c66f-82f7-4df0-0f92-8b9113be6f2
则执行上述脚本文件:
./ shutdown.sh /opt/VirtualBox-1.6.4/VirtualBox -comment winxp -startvm 5e04c66f-82f7-4df0-0f92-8b9113be6f2
监测开始
当虚拟机关机后命令行出现如下提示:
Done..shuting down in 60 seconds.
60秒后就会关机拉,如果你还不想关机,可以Ctrl+Alt+C停止当前任务,再进行其他操作,怎么样,挺好使的
--------------------------
09博客园纪念T恤新闻:
中国联通:国际通讯已恢复至震前水平网站导航:
博客园首页 个人主页 新闻 社区 博问 闪存 找找看文章来源:
http://www.cnblogs.com/xiaoao808/archive/2008/08/21/1273554.html
posted @
2008-08-21 22:25 破名超难起 阅读(506) |
评论 (0) |
编辑 收藏