发布新日志

  • Accessibility testing小结(一)

    zgnmgly 发布于 2007-11-26 22:27:20

    1.Overview of accessibilty testing

    Accessibilty testing就是测试软件能否被多种用户特别是残疾人群使用,是否有盲人使用的screen reader,,这其中也包含了正常人在某些时候发生暂时性障碍的情况下能否正常使用,是否支持全键盘操作等.

    一般情况下accessibility are recommendations for good user interface design.但是现在大公司都要求自身公司产品满足accessibility的属性,有的国家如美国也出台了关于accessibility的实施的法律.

    2.Accessible Software的三个基本原则

    1)Choice of input methods

    Input methods including keyboard, mouse, voice, and assistive devices via the serial port. The primary requirement is to provide keyboard access (mouseless operation) to all features and functions of the software application.

    2)Choice of output methods

    Output methods including display, sound, and print. The primary requirement is to provide text labels for icons, graphics, and user interface elements and to support visual indications for sounds.

    3)Consistency and flexibility

    Make the application consistent with the user's choice of system behavīor, colors, fonts sizes, and keyboard settings.

    3.Accessible Software的checklist和技巧

    1.1) Keyboard equivalents

    通过键盘的操作完成软件功能的实现

    a.软件应当同Keys used in Windows所描述内容相一致,如特殊键命令,ALT+F4是关闭窗口,Ctrl+P是打印

    b.能够使用TAB键切换聚焦,使用ENTER进行相关的操作,使用SHIFT+TAB组合向后切换聚焦。

    c.能够使用F6或CTRL+TAB切换窗口

    d.如果设置SPI_GETKEYBOARDPREF为true就显示了附加的键盘接口信息。这样用键盘操作更方便。

    1.2)Document Keyboard Access

    提供全键盘操作的方法的文档包括进入菜单键盘导航和快捷键

    a.提供键盘辅助的帮助文档。

    b.提供键盘辅助的索引项。

    c.产品文档包含“keyboard access”部分,归档所有辅助的功能点。

    d.提供与键盘操作等同的下拉菜单。标注好快捷键和加速键。

    1.3)Accelerator, mnemonic or shortcut keys

    给频繁使用的功能点定义快捷键\记忆键\加速键。

    a.除了动态菜单,每个菜单项都应该有加速键。

    b.可以参照windows软件设计键盘用户接口。http://microsoft.com/enable/提供许多有价值的文档。

    c.Windows软件隐藏了一些用户接口信息,可以通过设置用户控制面板,显示出所有的附加的键盘用户接口信息。

    1.4)Keyboard tab order

    按钮和列表的切换顺序要符合逻辑。导航的顺序通常是从左到右,从上到下。

    2.1)Accessibility features

    不要乱动操作系统中已经存在的辅助功能点。(不如粘滞键,显示声音和连续键等)

    操作系统通常都包含一些列辅助选项,需要用户自定义设置键盘,显示,声音和鼠标等。 

    Windows的键盘布置如表格

    Keyboard Mappings

    Mobility Access Feature

    5 consecutive clicks of Shift key

           On/Off for StickyKeys

    Right Shift held down 8 seconds

           On/Off FilterKeys

    NumLock held down 5 seconds

           On/Off ToggleKeys

    Left-Alt+Left-Shift+PrintScreen

           On/Off HighContrast

    Left-Alt+Left-Shift+NumLock

           On/Off MouseKeys

    3.1)Object focus:定义视觉焦点指示器,测试时候注意菜单和对话框以及属性窗口等,是否有TAB键容易切换聚焦,并且聚焦是否清晰可见。

    3.2)Object information:对用户接口对象提供辅助操作的信息。例如对盲人提供帮助作用的screen reader 和braille displays。例如screen reader可以告诉用户当前聚焦的对象的属性和状态。测试的时候,打开object inspector,把鼠标移到对象上,确认相关的信息是否正确。

    4.1)Labels associated with controls or objects:控件的标记信息。测试时候,打开object inspector,观察控件的标注信息是否正确。

    4.2)Positioning related objects:各项目按照逻辑或功能进行分组,有条理的安排顺序,并把重要的项目放到起始位置。测试的时候打开screen reader听各个控件和项目是否按照一定的逻辑顺序。

    5.1)Option to display audio alerts:对于有声音警告的也要有视觉提示。

    5.3) Visual display of information in video format:如果提供的重要信息是视频格式的,也要有提供同样信息的其它可达方法。测试的时候对软件输出的视频信息看是否可以用文本描述。

    5.4)Disable sounds and adjust volume:提供关闭声音和调整音量的选项。

    6.1)Displaying text:辅助功能的文本内容,包括文本输入脱字符号的位置和文本的属性.测试的时候打开screen reader,确认是否能多处所有的文本.

    6.2)Using color to convey information:确保所有信息有没有颜色都能呈现出来.技术要求对象要有文本描述,为了强调重要最好有图形或字符的提示,如星号,也可以使用粗体或斜体区分文本.测试的时候,打印屏幕截图,确认所有信息都存在,对于windows的应用软件,设置高对比度进行测试.

  • 多窗口页面(Frames)

    紫忧 发布于 2007-06-27 10:27:45

    基本语法:

    <frameset> ... </frameset>
    <frame src="url">
    <noframes> ... </noframes>

    在 <noframes> 标记后的文字将只出现在不支持 FRAMES 的浏览器中。

            <HTML>
            <HEAD>
            </HEAD>
            <FRAMESET>
                 <FRAME SRC="url">
                 <NOFRAMES> ... </NOFRAMES>
            </FRAMESET>
            </HTML>

    各窗口的尺寸设置

    <frameset cols=#>

    纵向排列多个窗口:

    <frameset cols=30%,20%,50%>
    <frame src="A.html">
    <frame src="B.html">
    <frame src="C.html">
    </frameset>
    
    示例
    
    A  C
    
    

    <frameset rows=#>

    横向排列多个窗口:

    <frameset rows=25%,25%,50%>
    <frame src="A.html">
    <frame src="B.html">
    <frame src="C.html">
    </frameset>
    
    示例
    
    A
    B
    C
    
    

    COLS & ROWS

    纵横排列多个窗口:

    <frameset cols=20%,*>
    <frame src="A.html">
         <frameset rows=40%,*>
         <frame src="B.html">
         <frame src="C.html">
         </frameset>
    </frameset>
    
    示例
    
    A B
    C
    
    

    不允许各窗口改变大小 <frame noresize>

    缺省设置是允许各窗口改变大小的。
    
    

    各窗口间相互操作(Frame Target)

    窗口标识(Frame Name)
    <frame name=#>
    <a href=url target=#>

    <frameset cols=50%,50%>
    <frame src="A.html">
    <frame src="B.html" name="HELLO">
    </frameset>
    
    示例
    
    A B

    特殊的 4 类操作(很有用喔)

    <a href=url target=_blank> 新窗口
    <a href=url target=_self> 本窗口
    <a href=url target=_parent> 父窗口
    <a href=url target=_top> 整个浏览器窗口

    示例

    
    

    Frame 的外观(Appearance)

    各窗口边框的设置 <frame frameborder=#> #=yes, no / 1, 0

    <frameset rows=30%,*>
    <frame src="Acol.html" frameborder=1>
    <frameset cols=30%,*>
         <frame src="Bcol.html" frameborder=0>
         <frame src="Ccol.html" frameborder=0>
    </frameset>
    </frameset>
    
    示例
    

    (A 有边框,B、C 没有)

    A
    B C

    各窗口间空白区域的设置
    <frameset framespacing=#> #=空白区域的大小

    <frameset rows=30%,* framespacing=100>
    <frame src="Acol.html">
    <frameset cols=30%,*>
         <frame src="Bcol.html">
         <frame src="Ccol.html">
    </frameset>
    </frameset>
    
    示例
    
    A
    B C

    边框色彩 <frameset bordercolor=#>

    #=rrggbb 16 进制 RGB 数码, 或者是下列预定义色彩名称:
    Black, Olive, Teal, Red, Blue, Maroon, Navy, Gray, Lime,
    Fuchsia, White, Green, Purple, Silver, Yellow, Aqua
    <frameset rows=30%,* bordercolor=red>
    <frame src="Acol.html">
    <frameset cols=30%,*>
         <frame src="Bcol.html">
         <frame src="Ccol.html">
    </frameset>
    </frameset>
    
    示例
    
    A
    B C

    页面空白(Margin) <frame marginwidth=# marginheight=#>

    <frameset cols=50%,50%>
    <frame src="A.html">
    <frame src="A.html" 
        marginwidth=50 
        marginheight=50>
    </frameset>
    
    示例
    
    AAAA AA
    AA

    卷滚条设置 <frame scrolling=#> #=yes, no, auto

    #=缺省值是 auto。
    
    

    浮动窗口(Floating Frame)

    <iframe src=# name=##> ... </iframe>
    #=初始页面的 URL
    ##=窗口标识(Frame Name)(之后可对此标识进行各窗口间相互操作)
    ... = 此处文字将只出现在不支持 FRAMES 的浏览器中。

    <center>
    <iframe src="A.html" name="window">
       Here is a Floating Frame
    </iframe>
    <br><br>
    <a href="A.html" target="window">Load A</A><BR>
    <a href="B.html" target="window">Load B</A><BR>
    <a href="Ccol.html" target="window">Load C</A><BR>
    </center>
    
    示例
    
    Display A.html


    Load A
    Load B
    Load C

  • APPSCAN 修复SQL注入安全缺陷建议[zt]

    liangjz 发布于 2008-03-20 22:29:29

     最近在了解IBM 的安全测试工具APPSCAN.

     通过使用demo.testfire.com。感觉功能确实NB。

     找个临时license尝试下扫描自己的测试环境,看看是否也这么好的命中率?

     另外,还有疑问它工作原理是否通过网络截取包,并解析特征字?

      对于hibernate、ibatis 这种封装SQL的代码是否也能判断到?

     

    Blind SQL Injection
    Fix Recommendation

    --------------------------------------------------------------------------------
    General
    There are several issues whose remediation lies in sanitizing user input.
    By verifying that user input does not contain hazardous characters, it is possible to prevent malicious users from causing your application to execute unintended operations, such as launch arbitrary SQL queries, embed Javascrīpt code to be executed on the client side, run various operating system commands etc.

    It is advised to filter out all the following characters:

    [1] | (pipe sign)
    [2] & (ampersand sign)
    [3] ; (semicolon sign)
    [4] $ (dollar sign)
    [5] % (percent sign)
    [6] @ (at sign)
    [7] ' (single apostrophe)
    [8] " (quotation mark)
    [9] \' (backslash-escaped apostrophe)
    [10] \" (backslash-escaped quotation mark)
    [11] <> (triangular parenthesis)
    [12] () (parenthesis)
    [13] + (plus sign)
    [14] CR (Carriage return, ASCII 0x0d)
    [15] LF (Line feed, ASCII 0x0a)
    [16] , (comma sign)
    [17] \ (backslash)


    The following sections describe the various issues, their fix recommendations and the hazardous characters that might trigger these issues:


    SQL injection and blind SQL injection:
    A. Make sure the value and type (such as Integer, Date, etc.) of the user input is valid and expected by the application.
    B. Use stored procedures to abstract data access so that users do not directly access tables or views. When using stored procedures, use the ADO command object to implement them, so that variables are strongly typed.
    C. Sanitize input to exclude context-changing symbols such as:

    [1] ' (single apostrophe)
    [2] " (quotation mark)
    [3] \' (backslash-escaped apostrophe)
    [4] \" (backslash-escaped quotation mark)
    [5] ) (closing parenthesis)
    [6] ; (semicolon)


    Cross site scrīpting:
    A. Sanitize user input and filter out Javascrīpt code. We suggest that you filter the following characters:

    [1] <> (triangular parenthesis)
    [2] " (quotation mark)
    [3] ' (single apostrophe)
    [4] % (percent sign)
    [5] ; (semicolon)
    [6] () (parenthesis)
    [7] & (ampersand sign)
    [8] + (plus sign)
    B. To fix the <%00scrīpt> variant see MS article 821349
    C. For UTF-7 attacks:

    [-] When possible, it is recommended to enforce a specific charset encoding (using 'Content-Type' header or <meta> tag).

    HTTP response splitting:
    Sanitize user input (at least, such input that is later embedded in HTTP responses).
    Make sure that malicious characters are not part of the input, such as:

    [1] CR (Carriage return, ASCII 0x0d)
    [2] LF (Line feed, ASCII 0x0a)


    Remote command execution:
    Sanitize input to exclude symbols that are meaningful to the operating system's command execution, such as:

    [1] | (pipe sign)
    [2] & (ampersand sign)
    [3] ; (semicolon sign)

    Shell command execution:
    A. Never pass unchecked user-input to Perl commands such as: eval(), open(), sysopen(), system().
    B. Make sure malicious characters are not part of the input, such as:

    [1] $ (dollar sign)
    [2] % (percent sign)
    [3] @ (at sign)


    XPath injection:
    Sanitize input to exclude context changing symbols such as:

    [1] ' (single apostrophe)
    [2] " (quotation mark)
    Etc.

    LDAP injection:
    A. Use positive validation. Alphanumeric filtering (A..Z,a..z,0..9) is suitable for most LDAP queries.
    B. Special LDAP characters which should be filtered out or escaped:

    [1] A space or "#" character at the beginning of the string
    [2] A space character at the end of the string
    [3] , (comma sign)
    [4] + (plus sign)
    [5] " (quotation mark)
    [6] \ (backslash)
    [7] <> (triangular parenthesis)
    [8] ; (semicolon sign)
    [9] () (parenthesis)
    Asp.Net
    Here are two possible ways to protect your web application against SQL injection attacks:

    [1] Use a stored procedure rather than dynamically built SQL query string. The way parameters are passed to SQL Server stored procedures, prevents the use of apostrophes and hyphens.

    Here is a simple example of how to use stored procedures in ASP.NET:


      ' Visual Basic example
      Dim DS As DataSet
      Dim MyConnection As SqlConnection
      Dim MyCommand As SqlDataAdapter
      Dim SelectCommand As String = "select * from users where username = @username"
      ...
      MyCommand.SelectCommand.Parameters.Add(New SqlParameter("@username", SqlDbType.NVarChar, 20))
      MyCommand.SelectCommand.Parameters("@username").Value = UserNameField.Value
      // C# example
      String selectCmd = "select * from Authors where state = @username";
      SqlConnection myConnection = new SqlConnection("server=...");
      SqlDataAdapter myCommand = new SqlDataAdapter(selectCmd, myConnection);
      myCommand.SelectCommand.Parameters.Add(new SqlParameter("@username", SqlDbType.NVarChar, 20));
      myCommand.SelectCommand.Parameters["@username"].Value = UserNameField.Value;

     

    [2] You can add input validation to Web Forms pages by using validation controls. Validation controls provide an easy-to-use mechanism for all common types of standard validation - for example, testing for valid dates or values within a range - plus ways to provide custom-written validation. In addition, validation controls allow you to completely customize how error information is displayed to the user. Validation controls can be used with any controls that are processed in a Web Forms page's class file, including both HTML and Web server controls.

    In order to make sure user input contains only valid values, you can use one of the following validation controls:


    a. "RangeValidator": checks that a user's entry (value) is between specified lower and upper boundaries. You can check ranges within pairs of numbers, alphabetic characters, and dates.


    b. "RegularExpressionValidator": checks that the entry matches a pattern defined by a regular expression. This type of validation allows you to check for predictable sequences of characters, such as those in social security numbers, e-mail addresses, telephone numbers, postal codes, and so on.

    Important note: validation controls do not block user input or change the flow of page processing; they only set an error state, and produce error messages. It is the programmer's responsibility to test the state of the controls in the code before performing further application-specific actions.

    There are two ways to check for user input validity:

    1. Testing for a general error state:

    In your code, test the page's IsValid property. This property rolls up the values of the IsValid properties of all the validation controls on the page (using a logical AND). If one of the validation controls is set to invalid, the page's property will return false.

    2. Testing for the error state of individual controls:

    Loop through the page's Validators collection, which contains references to all the validation controls. You can then examine the IsValid property of each validation control.
    J2EE
    ** Prepared Statements:

    There are 3 possible ways to protect your application against SQL injection, i.e. malicious tampering of SQL parameters. Instead of dynamically building SQL statements, use:

    [1] PreparedStatement, which is precompiled and stored in a pool of PreparedStatement objects. PreparedStatement defines setters to register input parameters that are compatible with the supported JDBC SQL data types. For example, setString should be used for input parameters of type VARCHAR or LONGVARCHAR (refer to the Java API for further details). This way of setting input parameters prevents an attacker from manipulating the SQL statement through injection of bad characters, such as apostrophe.

    Example of how to use a PreparedStatement in J2EE:


      // J2EE PreparedStatemenet Example
      // Get a connection to the database
      Connection myConnection;
      if (isDataSourceEnabled()) {
          // using the DataSource to get a managed connection
          Context ctx = new InitialContext();
          myConnection = ((DataSource)ctx.lookup(datasourceName)).getConnection(dbUserName, dbPassword);
      } else {
          try {
              // using the DriverManager to get a JDBC connection
              Class.forName(jdbcDriverClassPath);
              myConnection = DriverManager.getConnection(jdbcURL, dbUserName, dbPassword);
          } catch (ClassNotFoundException e) {
              ...
          }
      }
      ...
      try {
          PreparedStatement myStatement = myConnection.prepareStatement("select * from users where username = ?");
          myStatement.setString(1, userNameField);
          ResultSet rs = myStatement.executeQuery();
          ...
          rs.close();
      } catch (SQLException sqlException) {
          ...
      } finally {
          myStatement.close();
          myConnection.close();
      }

     

    [2] CallableStatement, which extends PreparedStatement to execute database SQL stored procedures. This class inherits input setters from PreparedStatement (see [1] above).

    The following example assumes that this database stored procedure has been created:

    CREATE PROCEDURE select_user (@username varchar(20))
    AS SELECT * FROM USERS WHERE USERNAME = @username;

    Example of how to use a CallableStatement in J2EE to execute the above stored procedure:


      // J2EE PreparedStatemenet Example
      // Get a connection to the database
      Connection myConnection;
      if (isDataSourceEnabled()) {
          // using the DataSource to get a managed connection
          Context ctx = new InitialContext();
          myConnection = ((DataSource)ctx.lookup(datasourceName)).getConnection(dbUserName, dbPassword);
      } else {
          try {
              // using the DriverManager to get a JDBC connection
              Class.forName(jdbcDriverClassPath);
              myConnection = DriverManager.getConnection(jdbcURL, dbUserName, dbPassword);
          } catch (ClassNotFoundException e) {
              ...
          }
      }
      ...
      try {
          PreparedStatement myStatement = myConnection.prepareCall("{?= call select_user ?,?}");
          myStatement.setString(1, userNameField);
          myStatement.registerOutParameter(1, Types.VARCHAR);
          ResultSet rs = myStatement.executeQuery();
          ...
          rs.close();
      } catch (SQLException sqlException) {
          ...
      } finally {
          myStatement.close();
          myConnection.close();
      }

     

    [3] Entity Bean, which represents an EJB business object in a persistent storage mechanism. There are two types of entity beans: bean-managed and container-managed. With bean-managed persistence, the developer is responsible of writing the SQL code to access the database (refer to sections [1] and [2] above). With container-managed persistence, the EJB container automatically generates the SQL code. As a result, the container is responsible of preventing malicious attempts to tamper with the generated SQL code.

    Example of how to use an Entity Bean in J2EE:


      // J2EE EJB Example
      try {
          // lookup the User home interface
          UserHome userHome = (UserHome)context.lookup(User.class);   
          // find the User remote interface
          User = userHome.findByPrimaryKey(new UserKey(userNameField));   
          ...   
      } catch (Exception e) {
          ...
      }

     

    RECOMMENDED JAVA TOOLS
    N/A

    REFERENCES
    http://java.sun.com/j2se/1.4.1/docs/api/java/sql/PreparedStatement.html
    http://java.sun.com/j2se/1.4.1/docs/api/java/sql/CallableStatement.html


    ** Input Data Validation:

    While data validations may be provided as a user convenience on the client-tier, data validation must be performed on the server-tier using Servlets. Client-side validations are inherently insecure because they can be easily bypassed, e.g. by disabling Javascrīpt.

    A good design usually requires the web application framework to provide server-side utility routines to validate the following:
    [1] Required field
    [2] Field data type (all HTTP request parameters are Strings by default)
    [3] Field length
    [4] Field range
    [5] Field options
    [6] Field pattern
    [7] Cookie values
    [8] HTTP Response

    A good practice is to implement the above routine as static methods in a "Validator" utility class. The following sections describe an example validator class.

    [1] Required field
    Always check that the field is not null and its length is greater than zero, excluding leading and trailing white spaces.

    Example of how to validate required fields:


      // Java example to validate required fields
      public Class Validator {
          ...
          public static boolean validateRequired(String value) {
              boolean isFieldValid = false;
              if (value != null && value.trim().length() > 0) {
                  isFieldValid = true;
              }
              return isFieldValid;
          }
          ...
      }
      ...
      String fieldValue = request.getParameter("fieldName");
      if (Validator.validateRequired(fieldValue)) {
          // fieldValue is valid, continue processing request
          ...
      }

     

    [2] Field data type
    In web applications, input parameters are poorly typed. For example, all HTTP request parameters or cookie values are of type String. The developer is responsible for verifying the input is of the correct data type. Use the Java primitive wrapper classes to check if the field value can be safely converted to the desired primitive data type.

    Example of how to validate a numeric field (type int):


      // Java example to validate that a field is an int number
      public Class Validator {
          ...
          public static boolean validateInt(String value) {
              boolean isFieldValid = false;
              try {
                  Integer.parseInt(value);
                  isFieldValid = true;
              } catch (Exception e) {
                  isFieldValid = false;
              }
              return isFieldValid;
          }
          ...
      }
      ...
      // check if the HTTP request parameter is of type int
      String fieldValue = request.getParameter("fieldName");
      if (Validator.validateInt(fieldValue)) {
          // fieldValue is valid, continue processing request
          ...
      }

     

    A good practice is to convert all HTTP request parameters to their respective data types. For example, the developer should store the "integerValue" of a request parameter in a request attribute and use it as shown in the following example:


      // Example to convert the HTTP request parameter to a primitive wrapper data type
      // and store this value in a request attribute for further processing
      String fieldValue = request.getParameter("fieldName");
      if (Validator.validateInt(fieldValue)) {
          // convert fieldValue to an Integer
          Integer integerValue = Integer.getInteger(fieldValue);
          // store integerValue in a request attribute
          request.setAttribute("fieldName", integerValue);
      }
      ...
      // Use the request attribute for further processing
      Integer integerValue = (Integer)request.getAttribute("fieldName");
      ...

     

    The primary Java data types that the application should handle:
    - Byte
    - Short
    - Integer
    - Long
    - Float
    - Double
    - Date

    [3] Field length
    Always ensure that the input parameter (whether HTTP request parameter or cookie value) is bounded by a minimum length and/or a maximum length.

    Example to validate that the length of the userName field is between 8 and 20 characters:


      // Example to validate the field length
      public Class Validator {
          ...
          public static boolean validateLength(String value, int minLength, int maxLength) {
              String validatedValue = value;
              if (!validateRequired(value)) {
                  validatedValue = "";
              }
              return (validatedValue.length() >= minLength &&
                          validatedValue.length() <= maxLength);
          }
          ...
      }
      ...
      String userName = request.getParameter("userName");
      if (Validator.validateRequired(userName)) {
          if (Validator.validateLength(userName, 8, 20)) {
              // userName is valid, continue further processing
              ...
          }
      }

     

    [4] Field range
    Always ensure that the input parameter is within a range as defined by the functional requirements.

    Example to validate that the input numberOfChoices is between 10 and 20:


      // Example to validate the field range
      public Class Validator {
          ...
          public static boolean validateRange(int value, int min, int max) {
              return (value >= min && value <= max);
          }
          ...
      }
      ...
      String fieldValue = request.getParameter("numberOfChoices");
      if (Validator.validateRequired(fieldValue)) {
          if (Validator.validateInt(fieldValue)) {
              int numberOfChoices = Integer.parseInt(fieldValue);
              if (Validator.validateRange(numberOfChoices, 10, 20)) {
                  // numberOfChoices is valid, continue processing request
                  ...
              }
          }
      }

     

    [5] Field options
    Often, the web application presents the user with a set of options to choose from, e.g. using the SELECT HTML tag, but fails to perform server-side validation to ensure that the selected value is one of the allowed options. Remember that a malicious user can easily modify any option value. Always validate the selected user value against the allowed options as defined by the functional requirements.

    Example to validate the user selection against a list of allowed options:


      // Example to validate user selection against a list of options
      public Class Validator {
          ...
          public static boolean validateOption(Object[] options, Object value) {
              boolean isValidValue = false;
              try {
                  List list = Arrays.asList(options);
                  if (list != null) {
                      isValidValue = list.contains(value);
                  }
              } catch (Exception e) {
              }
              return isValidValue;
          }
          ...
      }
      ...
      // Allowed options
      String[] ōptions = {"option1", "option2", "option3");
      // Verify that the user selection is one of the allowed options
      String userSelection = request.getParameter("userSelection");
      if (Validator.validateOption(options, userSelection)) {
          // valid user selection, continue processing request
          ...
      }

     

    [6] Field pattern
    Always check that the user input matches a pattern as defined by the functionality requirements. For example, if the userName field should only allow alpha-numeric characters, case insensitive, then use the following regular expression:
    ^[a-zA-Z0-9]*$

    Java 1.3 or earlier versions do not include any regular expression packages. Apache Regular Expression Package (see Resources below) is recommended for use with Java 1.3 to resolve this lack of support. Example to perform regular expression validation:


      // Example to validate that a given value matches a specified pattern
      // using the Apache regular expression package
      import org.apache.regexp.RE;
      import org.apache.regexp.RESyntaxException;
      public Class Validator {
          ...
          public static boolean matchPattern(String value, String expression) {
              boolean match = false;
              if (validateRequired(expression)) {
                   RE r = new RE(expression);
                   match = r.match(value);            
              }
              return match;
          }
          ...
      }
      ...
      // Verify that the userName request parameter is alpha-numeric
      String userName = request.getParameter("userName");
      if (Validator.matchPattern(userName, "^[a-zA-Z0-9]*$")) {
          // userName is valid, continue processing request
          ...
      }

     

    Java 1.4 introduced a new regular expression package (java.util.regex). Here is a modified version of Validator.matchPattern using the new Java 1.4 regular expression package:


      // Example to validate that a given value matches a specified pattern
      // using the Java 1.4 regular expression package
      import java.util.regex.Pattern;
      import java.util.regexe.Matcher;
      public Class Validator {
          ...
          public static boolean matchPattern(String value, String expression) {
              boolean match = false;
              if (validateRequired(expression)) {
                  match = Pattern.matches(expression, value);
              }
              return match;
          }
          ...
      }

     

    [7] Cookie value
    Use the javax.servlet.http.Cookie object to validate the cookie value. The same validation rules (described above) apply to cookie values depending on the application requirements, e.g. validate a required value, validate length, etc.

    Example to validate a required cookie value:


      // Example to validate a required cookie value
      // First retrieve all available cookies submitted in the HTTP request
      Cookie[] cookies = request.getCookies();
      if (cookies != null) {
          // find the "user" cookie
          for (int i=0; i<cookies.length; ++i) {
              if (cookies[i].getName().equals("user")) {
                  // validate the cookie value
                  if (Validator.validateRequired(cookies[i].getValue()) {
                      // valid cookie value, continue processing request
                      ...
                  }
              }   
          }
      }

     

    [8] HTTP Response
    [8-1] Filter user input
    To guard the application against cross-site scrīpting, sanitize HTML by converting sensitive characters to their corresponding character entities. These are the HTML sensitive characters:
    < > " ' % ; ) ( & +

    Example to filter a specified string by converting sensitive characters to their corresponding character entities:


      // Example to filter sensitive data to prevent cross-site scrīpting
      public Class Validator {
          ...
          public static String filter(String value) {
              if (value == null) {
                  return null;
              }       
              StringBuffer result = new StringBuffer(value.length());
              for (int i=0; i<value.length(); ++i) {
                  switch (value.charAt(i)) {
                  case '<':
                      result.append("&lt;");
                      break;
                  case '>':
                      result.append("&gt;");
                      break;
                  case '"':
                      result.append("&quot;");
                      break;
                  case '\'':
                      result.append("&#39;");
                      break;
                  case '%':
                      result.append("&#37;");
                      break;
                  case ';':
                      result.append("&#59;");
                      break;
                  case '(':
                      result.append("&#40;");
                      break;
                  case ')':
                      result.append("&#41;");
                      break;
                  case '&':
                      result.append("&amp;");
                      break;
                  case '+':
                      result.append("&#43;");
                      break;
                  default:
                      result.append(value.charAt(i));
                      break;
              }       
              return result;
          }
          ...
      }
      ...
      // Filter the HTTP response using Validator.filter
      PrintWriter ōut = response.getWriter();
      // set output response
      out.write(Validator.filter(response));
      out.close();

     

    The Java Servlet API 2.3 introduced Filters, which supports the interception and transformation of HTTP requests or responses.

    Example of using a Servlet Filter to sanitize the response using Validator.filter:


      // Example to filter all sensitive characters in the HTTP response using a Java Filter.
      // This example is for illustration purposes since it will filter all content in the response, including HTML tags!
      public class SensitiveCharsFilter implements Filter {
          ...
          public void doFilter(ServletRequest request,
                          ServletResponse response,
                          FilterChain chain)
                  throws IOException, ServletException {
              PrintWriter ōut = response.getWriter();
              ResponseWrapper wrapper = new ResponseWrapper((HttpServletResponse)response);
              chain.doFilter(request, wrapper);
              CharArrayWriter caw = new CharArrayWriter();
              caw.write(Validator.filter(wrapper.toString()));
             
              response.setContentType("text/html");
              response.setContentLength(caw.toString().length());
              out.write(caw.toString());
              out.close();
          }
          ...
          public class CharResponseWrapper extends HttpServletResponseWrapper {
              private CharArrayWriter output;
              public String toString() {
                  return output.toString();
              }
         
              public CharResponseWrapper(HttpServletResponse response){
                  super(response);
                  ōutput = new CharArrayWriter();
              }
             
              public PrintWriter getWriter(){
                  return new PrintWriter(output);
              }
          }
      }
      }

     

    [8-2] Secure the cookie
    When storing sensitive data in a cookie, make sure to set the secure flag of the cookie in the HTTP response, using Cookie.setSecure(boolean flag) to instruct the browser to send the cookie using a secure protocol, such as HTTPS or SSL.

    Example to secure the "user" cookie:


      // Example to secure a cookie, i.e. instruct the browser to
      // send the cookie using a secure protocol
      Cookie cookie = new Cookie("user", "sensitive");
      cookie.setSecure(true);
      response.addCookie(cookie);

     

    RECOMMENDED JAVA TOOLS
    The two main Java frameworks for server-side validation are:
    [1] Jakarta Commons Validator (integrated with Struts 1.1)
    The Jakarta Commons Validator is a powerful framework that implements all the above data validation requirements. These rules are configured in an XML file that defines input validation rules for form fields. Struts supports output filtering of dangerous characters in the [8] HTTP Response by default on all data written using the Struts 'bean:write' tag. This filtering may be disabled by setting the 'filter=false' flag.

    Struts defines the following basic input validators, but custom validators may also be defined:
    required: succeeds if the field contains any characters other than whitespace.
    mask: succeeds if the value matches the regular expression given by the mask attribute.
    range: succeeds if the value is within the values given by the min and max attributes ((value >= min) & (value <= max)).
    maxLength: succeeds if the field is length is less than or equal to the max attribute.
    minLength: succeeds if the field is length is greater than or equal to the min attribute.
    byte, short, integer, long, float, double: succeeds if the value can be converted to the corresponding primitive.
    date: succeeds if the value represents a valid date. A date pattern may be provided.
    creditCard: succeeds if the value could be a valid credit card number.
    email: succeeds if the value could be a valid e-mail address.

    Example to validate the userName field of a loginForm using Struts Validator:

      <form-validation>
          <global>
              ...
              <validator name="required"
                  classname="org.apache.struts.validator.FieldChecks"
                  method="validateRequired"
                  msg="errors.required">
              </validator>
              <validator name="mask"
                  classname="org.apache.struts.validator.FieldChecks"
                  method="validateMask"
                  msg="errors.invalid">
              </validator>
              ...
          </global>
          <formset>
              <form name="loginForm">
                  <!-- userName is required and is alpha-numeric case insensitive -->
                  <field property="userName" depends="required,mask">
                      <!-- message resource key to display if validation fails -->
                      <msg name="mask" key="login.userName.maskmsg"/>
                      <arg0 key="login.userName.displayname"/>
                      <var>
                          <var-name>mask</var-name>
                          <var-value>^[a-zA-Z0-9]*$</var-value>
                      </var>
                  </field>
              ...
              </form>
              ...
          </formset>
      </form-validation>

     

    [2] JavaServer Faces Technology
    JavaServer Faces Technology is a set of Java APIs (JSR 127) to represent UI components, manage their state, handle events and input validation.

    The JavaServer Faces API implements the following basic validators, but custom validators may be defined:
    validate_doublerange: registers a DoubleRangeValidator on a component
    validate_length: registers a LengthValidator on a component
    validate_longrange: registers a LongRangeValidator on a component
    validate_required: registers a RequiredValidator on a component
    validate_stringrange: registers a StringRangeValidator on a component
    validator: registers a custom Validator on a component

    The JavaServer Faces API defines the following UIInput and UIOutput Renderers (Tags):
    input_date: accepts a java.util.Date formatted with a java.text.Date instance
    output_date: displays a java.util.Date formatted with a java.text.Date instance
    input_datetime: accepts a java.util.Date formatted with a java.text.DateTime instance
    output_datetime: displays a java.util.Date formatted with a java.text.DateTime instance
    input_number: accepts a numeric data type (java.lang.Number or primitive), formatted with a java.text.NumberFormat
    output_number: accepts a numeric data type (java.lang.Number or primitive), formatted with a java.text.NumberFormat
    input_text: accepts a text string of one line.
    output_text: displays a text string of one line.
    input_time: accepts a java.util.Date, formatted with a java.text.DateFormat time instance
    output_time: displays a java.util.Date, formatted with a java.text.DateFormat time instance
    input_hidden: allows a page author to include a hidden variable in a page
    input_secret: accepts one line of text with no spaces and displays it as a set of asterisks as it is typed
    input_textarea: accepts multiple lines of text
    output_errors: displays error messages for an entire page or error messages associated with a specified client identifier
    output_label: displays a nested component as a label for a specified input field
    output_message: displays a localized message

    Example to validate the userName field of a loginForm using JavaServer Faces:

      <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
      <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
      ...
      <jsp:useBean id="UserBean"
          class="myApplication.UserBean" scope="session" />
      <f:use_faces>
        <h:form formName="loginForm" >
          <h:input_text id="userName" size="20" modelReference="UserBean.userName">
              <f:validate_required/>
              <f:validate_length minimum="8" maximum="20"/>   
          </h:input_text>
          <!-- display errors if present -->
          <h:output_errors id="loginErrors" clientId="userName"/>
          <h:command_button id="submit" label="Submit" commandName="submit" /><p>
        </h:form>
      </f:use_faces>

     


    REFERENCES
    Java API 1.3 - http://java.sun.com/j2se/1.3/docs/api/
    Java API 1.4 - http://java.sun.com/j2se/1.4/docs/api/
    Java Servlet API 2.3 - http://java.sun.com/products/servlet/2.3/javadoc/
    Java Regular Expression Package - http://jakarta.apache.org/regexp/
    Jakarta Validator - http://jakarta.apache.org/commons/validator/
    JavaServer Faces Technology - http://java.sun.com/j2ee/javaserverfaces/

    ** Error Handling:

    Many J2EE web application architectures follow the Model View Controller (MVC) pattern. In this pattern a Servlet acts as a Controller. A Servlet delegates the application processing to a JavaBean such as an EJB Session Bean (the Model). The Servlet then forwards the request to a JSP (View) to render the processing results. Servlets should check all input, output, return codes, error codes and known exceptions to ensure that the expected processing actually occurred.

    While data validation protects applications against malicious data tampering, a sound error handling strategy is necessary to prevent the application from inadvertently disclosing internal error messages such as exception stack traces. A good error handling strategy addresses the following items:

    [1] Defining Errors
    [2] Reporting Errors
    [3] Rendering Errors
    [4] Error Mapping

    [1] Defining Errors
    Hard-coded error messages in the application layer (e.g. Servlets) should be avoided. Instead, the application should use error keys that map to known application failures. A good practice is to define error keys that map to validation rules for HTML form fields or other bean properties. For example, if the "user_name" field is required, is alphanumeric, and must be unique in the database, then the following error keys should be defined:

    (a) ERROR_USERNAME_REQUIRED: this error key is used to display a message notifying the user that the "user_name" field is required;
    (b) ERROR_USERNAME_ALPHANUMERIC: this error key is used to display a message notifying the user that the "user_name" field should be alphanumeric;
    (c) ERROR_USERNAME_DUPLICATE: this error key is used to display a message notifying the user that the "user_name" value is a duplicate in the database;
    (d) ERROR_USERNAME_INVALID: this error key is used to display a generic message notifying the user that the "user_name" value is invalid;

    A good practice is to define the following framework Java classes which are used to store and report application errors:

    - ErrorKeys: defines all error keys


          // Example: ErrorKeys defining the following error keys:   
          //    - ERROR_USERNAME_REQUIRED
          //    - ERROR_USERNAME_ALPHANUMERIC
          //    - ERROR_USERNAME_DUPLICATE
          //    - ERROR_USERNAME_INVALID
          //    ...
          public Class ErrorKeys {
              public static final String ERROR_USERNAME_REQUIRED = "error.username.required";
              public static final String ERROR_USERNAME_ALPHANUMERIC = "error.username.alphanumeric";
              public static final String ERROR_USERNAME_DUPLICATE = "error.username.duplicate";
              public static final String ERROR_USERNAME_INVALID = "error.username.invalid";
              ...
          }

     

    - Error: encapsulates an individual error


          // Example: Error encapsulates an error key.
          // Error is serializable to support code executing in multiple JVMs.
          public Class Error implements Serializable {
             
              // Constructor given a specified error key
              public Error(String key) {
                  this(key, null);
              }
             
              // Constructor given a specified error key and array of placeholder objects
              public Error(String key, Object[] values) {
                  this.key = key;
                  this.values = values;
              }
             
              // Returns the error key
              public String getKey() {
                  return this.key;
              }
             
              // Returns the placeholder values
              public Object[] getValues() {
                  return this.values;
              }
             
              private String key = null;
              private Object[] values = null;
          }   

     

    - Errors: encapsulates a Collection of errors


          // Example: Errors encapsulates the Error objects being reported to the presentation layer.
          // Errors are stored in a HashMap where the key is the bean property name and value is an
          // ArrayList of Error objects.
          public Class Errors implements Serializable {
         
              // Adds an Error object to the Collection of errors for the specified bean property.
              public void addError(String property, Error error) {
                  ArrayList propertyErrors = (ArrayList)errors.get(property);
                  if (propertyErrors == null) {
                      propertyErrors = new ArrayList();
                      errors.put(property, propertyErrors);
                  }
                  propertyErrors.put(error);           
              }
             
              // Returns true if there are any errors
              public boolean hasErrors() {
                  return (errors.size > 0);
              }
             
              // Returns the Errors for the specified property
              public ArrayList getErrors(String property) {
                  return (ArrayList)errors.get(property);
              }
              private HashMap errors = new HashMap();
          }

     

    Using the above framework classes, here is an example to process validation errors of the "user_name" field:


      // Example to process validation errors of the "user_name" field.
      Errors errors = new Errors();
      String userName = request.getParameter("user_name");
      // (a) Required validation rule
      if (!Validator.validateRequired(userName)) {
          errors.addError("user_name", new Error(ErrorKeys.ERROR_USERNAME_REQUIRED));
      } // (b) Alpha-numeric validation rule
      else if (!Validator.matchPattern(userName, "^[a-zA-Z0-9]*$")) {
          errors.addError("user_name", new Error(ErrorKeys.ERROR_USERNAME_ALPHANUMERIC));
      }
      else
      {
          // (c) Duplicate check validation rule
          // We assume that there is an existing UserValidationEJB session bean that implements
          // a checkIfDuplicate() method to verify if the user already exists in the database.
          try {
              ...       
              if (UserValidationEJB.checkIfDuplicate(userName)) {
                  errors.addError("user_name", new Error(ErrorKeys.ERROR_USERNAME_DUPLICATE));
              }
          } catch (RemoteException e) {
              // log the error
              logger.error("Could not validate user for specified userName: " + userName);
              errors.addError("user_name", new Error(ErrorKeys.ERROR_USERNAME_DUPLICATE);
          }
      }
      // set the errors object in a request attribute called "errors"
      request.setAttribute("errors", errors);
      ...

     

    [2] Reporting Errors
    There are two ways to report web-tier application errors:
    (a) Servlet Error Mechanism
    (b) JSP Error Mechanism

    [2-a] Servlet Error Mechanism
    A Servlet may report errors by:
    - forwarding to the input JSP (having already stored the errors in a request attribute), OR
    - calling response.sendError with an HTTP error code argument, OR
    - throwing an exception

    It is good practice to process all known application errors (as described in section [1]), store them in a request attribute, and forward to the input JSP. The input JSP should display the error messages and prompt the user to re-enter the data. The following example illustrates how to forward to an input JSP (userInput.jsp):


      // Example to forward to the userInput.jsp following user validation errors
      RequestDispatcher rd = getServletContext().getRequestDispatcher("/user/userInput.jsp");
      if (rd != null) {
          rd.forward(request, response);
      }

     

    If the Servlet cannot forward to a known JSP page, the second option is to report an error using the response.sendError method with HttpServletResponse.SC_INTERNAL_SERVER_ERROR (status code 500) as argument. Refer to the javadoc of javax.servlet.http.HttpServletResponse for more details on the various HTTP status codes. Example to return a HTTP error:


      // Example to return a HTTP error code
      RequestDispatcher rd = getServletContext().getRequestDispatcher("/user/userInput.jsp");
      if (rd == null) {
          // messages is a resource bundle with all message keys and values
          response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
                                  messages.getMessage(ErrorKeys.ERROR_USERNAME_INVALID));
      }

     

    As a last resort, Servlets can throw an exception, which must be a subclass of one of the following classes:
    - RuntimeException
    - ServletException
    - IOException

    [2-b] JSP Error Mechanism
    JSP pages provide a mechanism to handle runtime exceptions by defining an errorPage directive as shown in the following example:


          <%@ page errorPage="/errors/userValidation.jsp" %>

     

    Uncaught JSP exceptions are forwarded to the specified errorPage, and the original exception is set in a request parameter called javax.servlet.jsp.jspException. The error page must include a isErrorPage directive as shown below:


          <%@ page isErrorPage="true" %>

     

    The isErrorPage directive causes the "exception" variable to be initialized to the exception object being thrown.

    [3] Rendering Errors
    The J2SE Internationalization APIs provide utility classes for externalizing application resources and formatting messages including:

    (a) Resource Bundles
    (b) Message Formatting

    [3-a] Resource Bundles
    Resource bundles support internationalization by separating localized data from the source code that uses it. Each resource bundle stores a map of key/value pairs for a specific locale.

    It is common to use or extend java.util.PropertyResourceBundle, which stores the content in an external properties file as shown in the following example:


      ################################################
      # ErrorMessages.properties
      ################################################
      # required user name error message
      error.username.required=User name field is required
      # invalid user name format
      error.username.alphanumeric=User name must be alphanumeric
      # duplicate user name error message
      error.username.duplicate=User name {0} already exists, please choose another one
      ...

     

    Multiple resources can be defined to support different locales (hence the name resource bundle). For example, ErrorMessages_fr.properties can be defined to support the French member of the bundle family. If the resource member of the requested locale does not exist, the default member is used. In the above example, the default resource is ErrorMessages.properties. Depending on the user's locale, the application (JSP or Servlet) retrieves content from the appropriate resource.

    [3-b] Message Formatting
    The J2SE standard class java.util.MessageFormat provides a generic way to create messages with replacement placeholders. A MessageFormat object contains a pattern string with embedded format specifiers as shown below:


      // Example to show how to format a message using placeholder parameters
      String pattern = "User name {0} already exists, please choose another one";
      String userName = request.getParameter("user_name");
      Object[] args = new Object[1];
      args[0] = userName;
      String message = MessageFormat.format(pattern, args);

     

    Here is a more comprehensive example to render error messages using ResourceBundle and MessageFormat:


      // Example to render an error message from a localized ErrorMessages resource (properties file)
      // Utility class to retrieve locale-specific error messages
      public Class ErrorMessageResource {
         
          // Returns the error message for the specified error key in the environment locale
          public String getErrorMessage(String errorKey) {
              return getErrorMessage(errorKey, defaultLocale);
          }
         
          // Returns the error message for the specified error key in the specified locale
          public String getErrorMessage(String errorKey, Locale locale) {
              return getErrorMessage(errorKey, null, locale);
          }
         
          // Returns a formatted error message for the specified error key in the specified locale
          public String getErrorMessage(String errorKey, Object[] args, Locale locale) {   
              // Get localized ErrorMessageResource
              ResourceBundle errorMessageResource = ResourceBundle.getBundle("ErrorMessages", locale);
              // Get localized error message
              String errorMessage = errorMessageResource.getString(errorKey);
              if (args != null) {
                  // Format the message using t

  • 转贴 使用 Rational AppScan 保证 Web 应用的安全性

    yanming_huo 发布于 2009-06-28 09:10:43

    使用 Rational AppScan 保证 Web 应用的安全性

    '); //--> '); //-->
    将打印机的版面设置成横向打印模式

    打印本页

     

    将此页作为电子邮件发送

    将此页作为电子邮件发送

     

    未显示需要 JavaScript. 的文档选项


     

    Web 应用现状

    Web 应用的基础概念

    在讨论 Web 应用安全之前,先简单介绍一下 Web 应用基础概念,这样便于理解为什么 Web 应用是脆弱的,容易受到攻击。

    1、 什么是 Web 应用

    Web 应用是由动态脚本、编译过的代码等组合而成。它通常架设在 Web 服务器上,用户在 Web 浏览器上发送请求,这些请求使用 HTTP 协议,经过因特网和企业的 Web 应用交互,由 Web 应用和企业后台的数据库及其他动态内容通信。

    2、 Web 应用的架构

    尽管不同的企业会有不同的 Web 环境搭建方式,一个典型的 Web 应用通常是标准的三层架构模型,如图 1 所示。


    图 1: Web 应用通常是标准的三层架构模型
    Web 应用通常是标准的三层架构模型

    在这种最常见的模型中,客户端是第一层;使用动态 Web 内容技术的部分属于中间层;数据库是第三层。用户通过 Web 浏览器发送请求(request)给中间层,由中间层将用户的请求转换为对后台数据的查询或是更新,并将最终的结果在浏览器上展示给用户。

    Web 应用安全全景

    当讨论起 Web 应用安全,我们经常会听到这样的回答:
    “我们使用了防火墙”、“我们使用了网络脆弱扫描工具”、“我们使用了 SSL 技术”、“我们每个季度都会进行渗透测试”……所以,“我们的应用是安全的”。现实真是如此吗?让我们一起来看一下 Web 应用安全的全景图。


    图 2: 信息安全全景
    信息安全全景

    在企业 Web 应用的各个层面,都会使用不同的技术来确保安全性。为了保护客户端机器的安全,用户会安装防病毒软件;为了保证用户数据传输到企业 Web 服务器的传输安全,通信层通常会使用 SSL(安全套接层)技术加密数据;企业会使用防火墙和 IDS(入侵诊断系统)/IPS(入侵防御系统)来保证仅允许特定的访问,不必要暴露的端口和非法的访问,在这里都会被阻止;即使有防火墙,企业依然会使用身份认证机制授权用户访问 Web 应用。

    但是,即便有防病毒保护、防火墙和 IDS/IPS,企业仍然不得不允许一部分的通讯经过防火墙,毕竟 Web 应用的目的是为用户提供服务,保护措施可以关闭不必要暴露的端口,但是 Web 应用必须的 80 和 443 端口,是一定要开放的。可以顺利通过的这部分通讯,可能是善意的,也可能是恶意的,很难辨别。这里需要注意的是,Web 应用是由软件构成的,那么,它一定会包含缺陷(bugs),这些 bug 就可以被恶意的用户利用,他们通过执行各种恶意的操作,或者偷窃、或者操控、或者破坏 Web 应用中的重要信息。

    因此可以看出,企业的回答,并不能真正保证企业的应用安全:

    • 网络脆弱性扫描工具,由于它仅仅用来分析网络层面的漏洞,不了解应用本身,所以不能彻底提高 Web 应用安全性;
    • 防火墙可以阻止对重要端口的访问,但是 80 和 443 端口始终要开放,我们无法判断这两个端口中通讯数据是善意的访问还是恶意的攻击;
    • SSL 可以加密数据,但是它仅仅保护了在传输过程中数据的安全性,并没有保护 Web 应用本身;
    • 每个季度的渗透测试,无法满足处于不断变更之中的应用。

    只要访问可以顺利通过企业的防火墙,Web 应用就毫无保留的呈现在用户面前。只有加强 Web 应用自身的安全,才是真正的 Web 应用安全解决之道。





    常见的 Web 应用攻击

    两个重要的国际应用安全组织

    在讨论常见的 Web 应用攻击之前,我们需要先了解两个组织:WASC 和 OWASP。这两个组织在呼吁企业加强应用安全意识和指导企业开发安全的 Web 应用方面,起到了重要的作用。

    Web Application Security Consortium(WASC),是一个由安全专家、行业顾问和诸多组织的代表组成的国际团体。他们负责为 WWW 制定被广为接受的应用安全标准。WASC 组织的关键项目之一是“Web 安全威胁分类”,也就是将 Web 应用所受到的威胁、攻击进行说明并归纳成具有共同特征的分类。该项目的目的是针对 Web 应用的安全隐患,制定和推广行业标准术语。WASC 将 Web 应用安全威胁分为如下六类:

    Authentication(验证)
    用来确认某用户、服务或是应用身份的攻击手段。
    Authorization(授权)
    用来决定是否某用户、服务或是应用具有执行请求动作必要权限的攻击手段。
    Client-Side Attacks(客户侧攻击)
    用来扰乱或是探测 Web 站点用户的攻击手段。
    Command Execution(命令执行)
    在 Web 站点上执行远程命令的攻击手段。
    Information Disclosure(信息暴露)
    用来获取 Web 站点具体系统信息的攻击手段。
    Logical Attacks(逻辑性攻击)
    用来扰乱或是探测 Web 应用逻辑流程的攻击手段。

    可以通过如下的网址访问该组织网站,获得更多详细信息:www.webappsec.org。也可以通过参考资料中链接,具体了解“Web 安全威胁分类”项目。

    Open Web Application Security Project(OWASP),该组织致力于发现和解决不安全 Web 应用的根本原因。它们最重要的项目之一是“Web 应用的十大安全隐患”,总结了目前 Web 应用最常受到的十种攻击手段,并且按照攻击发生的概率进行了排序。这个项目的目的是统一业界最关键的 Web 应用安全隐患,并且加强企业对 Web 应用安全的意识。


    图 3: Web 应用十大安全隐患
    Web 应用十大安全隐患

    可以通过如下的网址访问该组织,了解更为详细的信息:www.owasp.org。也可以通过参考资料中链接,具体了解“Web 应用十大安全隐患”项目。

    IBM Rational,是上述两个组织的成员。

    常见的 Web 应用攻击示例

    在 OWASP 组织列举的十大 Web 应用安全隐患中,有两个概率最高的攻击手段,它们分别是“跨站点脚本攻击”(Cross-Site Scripting)和“注入缺陷”(Injection Flaws)。下面将通过举例来说明这两种攻击是如何实施的。

    1、 跨站点脚本攻击

    首先来看一下跨站点脚本的利用过程,如图 4。


    图 4: 跨站点脚本攻击的过程
    跨站点脚本攻击的过程

    在上图中,恶意攻击者(这里使用 Evil.org 表示)通过 E-mail 或 HTTP 将某银行的网址链接发给用户(银行用 bank.com 表示),该链接中附加了恶意的脚本(上图步骤一);用户访问发来的链接,进入银行网站,同时,嵌在链接中的脚本被用户的浏览器执行(上图步骤二、三);用户在银行网站的所有操作,包括用户的 cookie 和 session 信息,都被脚本收集到,并且在用户毫不知情的情况下发送给恶意攻击者(上图步骤四);恶意攻击者使用偷来的 session 信息,伪装成该用户,进入银行网站,进行非法活动(上图步骤五)。

    因此,只要 Web 应用中,有可被恶意攻击者利用执行脚本的地方,都存在极大的安全隐患。黑客们如果可以让用户执行他们提供的脚本,就可以从用户正在浏览的域中偷到他的个人信息、可以完全修改用户看到的页面内容、跟踪用户在浏览器中的每一个动作,甚至利用用户浏览器的缺陷完全控制用户的机器。

    目前,跨站点脚本攻击是最大的安全风险。

    2、 注入缺陷

    目前的 Web 应用中,绝大多数都会向用户提供一个接口,用来进行权限验证、搜索、查询信息等功能。比如一个在线银行应用,首先会有对注册客户进行身份验证的登录界面,在正确登录后,会提供更多交互功能,如根据客户的银行卡号信息,查询客户的最近交易、转账细节等。这些都是注入缺陷的最佳利用场景。所谓注入缺陷,就是在上述场景中,用户输入的数据被当做命令和查询的一部分,送到后端的解释器中解释执行。如果用户的输入是正常合法的,Web 应用自然会返回正常合理的结果,但是,如果恶意攻击者,利用输入数据可被后台执行的原理,偷梁换柱,使用非法的输入,脆弱的 Web 应用会怎样呢?

    下面我们举一个例子来说明注入缺陷是如何进行的。在一个交易网站中,用户必须输入产品 ID 号才可以查看该产品的详细信息。为了实现这个需求,通常会用 SQL 语句查询数据库来实现。开发人员在编写应用程序时,可能会使用如下的 SQL 语句来实现上述目的(这里仅为示例):

    1) Select * from products where product_id = ` + 用户输入的 ID + `

    这里的 products 是数据库中用来存放产品信息的表,+号表示 SQL 语句需要和用户输入的真实 ID 进行拼接。如果用户输入 325,则该语句在执行时变为:

    Select * from products where product_id = ` 325 `
    

    数据库会将 ID 为 325 的产品信息返回给用户。

    2) 在界面上,需要用户输入产品 ID 的地方,黑客会输入如下数据:

    ` or `1`= `1
    

    可以看到,黑客并没有输入正常合法的产品编号。

    3) 通过黑客的非法输入,需要执行的 SQL 语句变为:

    Select * from products where product_id = ` ` or `1`=`1`
    

    可以看出,SQL 语句的意义就完全改变了,当产品 ID 为空或者 1=1 时,返回产品所有信息,而 1=1 是永远成立的条件,因此,黑客并没有输入任何产品编号,就可以返回数据库中所有产品的详细信息。

    通过这个例子,我们可以看出,注入缺陷是风险非常高的安全漏洞,一旦 Web 应用中给用户提供了需要其输入数据的接口,就有可能遭到攻击,将后台的数据完全暴露在用户的面前。

    上述说明的“跨站点脚本攻击”和“注入缺陷攻击”,是目前 Web 应用中比例最高的两种攻击手段,按照 OWASP 的项目排序,还有如下八种风险性较高的攻击方法:

    • Malicious File Execution(恶意文件执行);
    • Insecure Direct Object Reference(不安全的直接对象引用);
    • Cross-Site Request Forgery(跨站点的请求伪造);
    • Information Leakage and Improper Error Handling(信息泄漏和不正确的错误处理);
    • Broken Authentication & Session Management(损坏的认证和 Session 管理);
    • Insecure Cryptographic Storage(不安全的密码存储);
    • Insecure Communications(不安全的通信);
    • Failure to Restrict URL Access(未能限制 URL 访问)

    在这里,我们就不过多的讨论这几种安全隐患,可以使用 3.1 节中提供的链接得到更多的描述信息。





    回页首


    构筑安全的 Web 应用

    功能和性能,往往是我们衡量应用是否满足需求的指标,但是,对于载体为 Internet 的特殊应用-Web 应用而言,安全性也是必要的考量标准,皮之不存,毛将焉附?如果失去了安全性,即使功能再完备、性能再可靠的 Web 应用,一旦遭到黑客的攻击和破坏,一切都失去了意义。因此企业,尤其是提供 Web 应用的企业,一定要加强对应用安全的重视程度。

    针对目前 Web 应用安全性不高的现状,IBM Rational 提出了构筑安全 Web 应用的解决方案。

    加强全员应用安全性意识

    一个根本、底层的战略手段就是加强企业全员的应用安全意识。正如前面所阐述过的,对于应用而言,无论是开发人员、测试人员、质量管理人员还是项目经理、企业高层,都会对其功能和性能做更多的关注,这也是由于早期应用多为 C/S 架构的应用,安全问题并不突出。但是在当今的环境,就不得不将安全作为应用质量的基础。

    图 5 中功能、易用性、可靠性、性能、可支持性,是由 Rational Unified Process(RUP)定义的 FURPS 质量模型,它告诉我们应用的质量需要从这几个方面着手衡量,对于 Web 应用,就必须将安全性作为质量模型的基础条件。


    图 5: 适于 Web 应用的质量模型
    适于 Web 应用的质量模型

    要加强全员应用安全意识,就需要对每一个相关角色落实安全要求。

    1) 对于需求分析、设计人员而言,是否已将产品的安全性考虑到产品的需求设计中,从而保证在项目初期,安全因素已被关注;

    2) 对于开发人员,在应用中实现了身份认证等安全功能,并不意味着在编程中已考虑到了应用安全性,它们还必须掌握 Web 应用安全编程规范等技术;

    3) 对于测试人员,验证了应用的 FURPS,不能保证产品已具备安全性,还需要借助其他工具或平台,对应用的安全隐患,进行自动化的扫描,得出全面的安全性报告;

    4) 对于质量管理人员,产品的质量过关,也不等于产品已经安全可靠,他们和测试人员一样,需要借助工具,掌握 Web 应用全面的安全隐患汇总和分析。

    使用先进的工具确保软件开发生命周期中的安全性

    在企业全员都具有了应用安全意识之后,必须将该意识贯彻到项目的具体工作之中,除了要求每个人具备严谨认真、不断学习的态度之外,还需要借助先进的工具,对开发的 Web 应用进行自动化的安全隐患发现、分析、报告、提供修复意见等工作,建立人工检查和自动化工具配合的完整保障措施。IBM Rational AppScan,正是这样一种 Web 应用自动化诊断工具,下面我们对其进行简单的介绍。

    Rational AppScan,是对 Web 应用和 Web Services 进行自动化安全扫描的黑盒工具,它不但可以简化企业发现和修复 Web 应用安全隐患的过程(因为这些工作,以往都是由人工进行,成本相对较高,但是效率却非常低下),还可以根据发现的安全隐患,提出针对性的修复建议,并能形成多种符合法规、行业标准的报告,方便相关人员全面了解企业应用的安全状况。图 6 说明了 AppScan 在软件开发生命周期中的各个阶段,都可以协助安全隐患的诊断。


    图 6: AppScan 对软件开发生命周期的支持
    AppScan 对软件开发生命周期的支持

    1) 开发过程中的安全保障

    AppScan DE(AppScan 开发版)可以作为多种平台的插件,这些平台包括 Eclipse、WebSphere、Visual Studio、JBuilder,协助开发人员对编写的模块进行自我安全诊断。图 7 是 AppScan DE 作为 Visual Studio 插件使用的示例。


    图 7: AppScan DE 作为 Visual Studio 的插件
    AppScan DE 作为 Visual Studio 的插件

    2) 质量管理过程中的安全保障

    通过和 Rational ClearQuest 的集成,AppScan 可以将发现的安全隐患方便的导入到变更管理平台中,确保发现的每一个问题,都被记录,并详细跟踪其在整个修复过程中的状态变化。如图 8 所示。


    图 8: AppScan 和 Rational ClearQuest 集成
    AppScan 和 Rational ClearQuest 集成

    除 Rational ClearQuest 之外,AppScan 还可以和 Mercury 的 Quality Center 集成。

    3) 在集成和发布阶段中的安全保障

    在集成和发布阶段,可以通过简单的配置,使用 AppScan 对应用进行全面的扫描,企业仅需要指明 Web 应用的入口链接,AppScan 就会利用网络爬行(Crawling)技术,遍历应用中所有需要测试的链接,并对每个链接发送多种测试参数,诊断其有无漏洞可被利用。最后将结果呈现在用户面前。如图 9 是对示例网站 http://demo.testfire.net 进行诊断的结果。

    从结果可以看出,本次诊断共发现了 88 个安全隐患,并按照严重程度进行了统计。诊断结果的中部,显示了 AppScan 扫描出来的应用结构、每个模块或链接包含的漏洞数;右上方则按照严重程度,对扫描出来的漏洞进行了分类;结果的右下方对每一种隐患,进行了解释,并提出了详细的修复建议,同时说明了为发现这个漏洞,AppScan 发送了哪些测试参数等。


    图 9: AppScan 的诊断结果示例
    AppScan 的诊断结果示例

    4) 对诊断结果进行全面的分析和报告

    Rational AppScan 不仅可以对 Web 应用进行自动化的扫描、指出安全漏洞的修复意见,还可以将诊断结果,使用不同的行业标准、法规,形成针对性的报告,让相关人员对应用安全状况和法规遵从等有了全面的认识。如图 10,左图是 AppScan 可以自动生成的行业标准报告,而右图则是近 40 种的法规遵从报告,如赛班斯法规遵从等。


    图 10: 自动生成的行业标准报告
    自动生成的行业标准报告




    小结

    通过上述对 Web 应用现状和常见的 Web 应用攻击示例分析,我们可以看出,目前因特网上的 Web 应用,存在着极大的安全隐患和风险,企业对 Web 应用安全的保护,已经刻不容缓。IBM Rational AppScan,作为先进的 Web 应用自动化诊断工具,可以协助企业在整个 Web 应用开发生命周期,将安全意识贯彻到企业全员具体的工作中,高效率的发现应用中存在的安全隐患、给出详细的修复建议、并生成多种符合行业标准和法规的报告,已在全球拥有近千个成功案例,是一个完整的、端到端的 Web 应用安全解决方案,能真正为企业的 Web 应用披上安全的盔甲

  • AppScan测安全性问题关注点

    w_gq2003 发布于 2010-05-13 15:06:17

    用安全性测试工具AppScan进行安全性测试时的关注点:


  • Ruby+Watir经验谈: 包装Watir::IE

    lifr 发布于 2007-06-01 11:10:12

    如果我们要设计一个测试某个Web Server的框架,可以想象会经常在不同的页面跳转。在跳转的时候,你会希望只需提供url path而不是完整的url。但Watir::IE的goto方法需要全路径,所以一种方法是这样

        ie.goto("http://#{$serverip}:#{$serverport}/addUser"); # 用全局变量的方式

    但显然我们希望更好的调用方式是

        ie.goto("/addUser"); # 理想的调用方式

    二者的易用性差别不言而喻。但这就需要修改Watir::IE的行为,让他能接受url path的方式。在这里也体现了Ruby的强大之处,它的class定义是open的,你可以在任意一个地方修改它。


    module Watir
        # 修改Watir::IE就是这么简单
        class IE
        # 参数url定义了协议,地址,和端口
        # for example:
        #   * 10.10.10.10
        #   * 10.10.10.10:8080
        #   * http://10.10.10.10
        #   * https://10.10.10.10
        #
        # parameter 'attach' is a boolean, true means that if there is an existing IE browser,
        # don't launch a new one, jsut attach the ie object to it.
        #
        # @exception Watir::Exception::NoMatchingWindowFoundException if attaching failed
        def initialize(url, attach=false)
            Everbright::Basic.assert_true(!url.nil?, "occUrl shouldn't be nil")
            
            url = url.strip.upcase
            # "10.10.10.10" => [[nil, nil, "10.10.10.10"]]
            # "https://10.10.10.10" => [["https://", "https", "10.10.10.10"]]
            resultAry = url.scan( /^((https?):\/\/)?(.+)$/)
            @scheme, @occUrl = resultAry[0][0] || "http", resultAry[0][2]
            Everbright::Basic.assert_true(!@occUrl.nil?, "no site ip found from #{@occUrl}")

            if attach
            attach_init(:url, Regexp.compile(url))
            else
            create_browser_window
            set_defaults
            end
        end
            
        # 这个方法不应该被访问
            def IE.start( url = nil )
            raise Everbright::Basic::EverbrightException.new("The method shouldn't be called in Everbright framework")
            end

        # 这个方法不应该被访问
        def IE.attach(how, what)
            raise Everbright::Basic::EverbrightException.new("The method shouldn't be called in Everbright framework")
            end


        alias _goto goto

        # 我们需要重写goto方法
        #
            # URL is like: /gateway/login.jsp?user=.....
        # URL shouldn't be like: http://10.10.10.10/gateway/login.jsp.....
        def goto(path)
            return nil if path.nil?
            Everbright::Basic.assert_true(!(path =~ /^https?:\/\//), "URL should be like: /gateway/login....")
           
            log "goto: #{path}"
                _goto("#{@scheme}://#{@occUrl}#{path}")
            end

        end
    end

    这样,一个在其他语言里实现起来非常麻烦的功能,在ruby里只是a piece of cake.

    在c++里,需要实现一个wrapper,把Watir::IE的每个方法都重写一遍,虽然大多数都是简单的转发。在java里要容易点,如果在容器里流行的是AOP拦截,应该也可以使用DynamicProxy这个高级功能,但总之没有ruby来的优美漂亮。
  • 网络公司常问到的端口

    v_v 发布于 2007-06-14 23:14:55

    端口便是计算机与外部通信的途径,没有它,计算机便又聋又哑。一个端口就是一个潜在的通信通道,也就是一个入侵通道。
    先说服务,我们首先要明白“连接”和“无连接”的概念。最简单的例子莫过于打电话和写信。两个人如果要通电话,得首先建立连接——即拨号,等待应答后才能相互传递信息,最后还要释放连接——即挂电话。写信就没有那么复杂了,地址姓名填好以后直接往邮筒一扔,收信人就能收到。
    因特网上最流行的协议是TCP/IP协议,需要说明的是,TCP/IP协议在网络层是无连接的(数据包只管往网上发,如何传输和到达以及是否到达由网络设备来管理)。而我们一旦谈“端口”,就已经到了传输层。协议里面低于1024的端口都有确切的定义,它们对应着因特网上常见的一些服务。这些常见的服务可以划分为使用TCP端口(面向连接如打电话)和使用UDP端口(无连接如写信)两种。
    使用TCP端口常见的有:
    ftp:定义了文件传输协议,使用21端口。常说某某主机开了 ftp服务便是文件传输服务。下载文件,上传主页,都要用到ftp服务。
    telnet:你上BBS吗?以前的BBS是纯字符界面的,支持BBS的服务器将23端口打开,对外提供服务。其实Telnet的真正意思是远程登陆:用户可以以自己的身份远程连接到主机上。
    smtp:定义了简单邮件传送协议。现在很多邮件服务器都用的是这个协议,用于发送邮件。服务器开放的是25端口。
    http:这可是大家用得最多的协议了——超文本传送协议。上网浏览网页就需要用到它,那么提供网页资源的主机就得打开其80端口以提供服务。我们常说“提供www服务”、“Web服务器”就是这个意思。
    pop3:和smtp对应,pop3用于接收邮件。通常情况下,pop3协议所用的是110端口。在263等免费邮箱中,几乎都有pop3收信功能。也就是说,只要你有相应的使用pop3协议的程序(例如Foxmail或Outlook),不需要从Web方式登陆进邮箱界面,即可以收信。
    使用UDP端口常见的有:
    DNS:域名解析服务。因特网上的每一台计算机都有一个网络地址与之对应,这个地址就是我们常说的IP地址,它以纯数字的形式表示。然而这却不便记忆,于是出现了域名。访问主机的时候只需要知道域名,域名和IP地址之间的变换由DNS服务器来完成。DNS用的是53端口。
    snmp:简单网络管理协议,使用161端口,是用来管理网络设备的。由于网络设备很多,无连接的服务就体现出其优势。
    聊天软件Oicq:Oicq的程序既接受服务,又提供服务,这样两个聊天的人才是平等的。oicq用的是无连接的协议,其服务器使用8000端口,侦听是否有信息到来;客户端使用4000端口,向外发送信息。如果上述两个端口正在使用(有很多人同时和几个好友聊天),就顺序往上加。
    以上是计算机常用的一些端口,此外还有很多端口,由于我们这次实验没用到,所以就不一一介绍了。
    1、端口的扫描
    端口扫描的方法现在有N种,最常用,也是最简捷的方法就是在任务栏里点开始、运行框里输入cmd,出现一个DOS框,输入netatat –an,那么你电脑目前所有的端口状况就一览无余。
    2、端口的关闭
           3389端口的关闭:
    首先说明3389端口是windows的远程管理终端所开的端口,它并不是一个木马程序,请先确定该服务是否是你自己开放的。如果不是必须的,请关闭该服务。
    方法: 在我的电脑上点右键选属性-->远程,将里面的远程协助和远程桌面两个选项框里的勾去掉。
           4899端口的关闭:
    首先说明4899端口是一个远程控制软件(remote administrator)服务端监听的端口,他不能算是一个木马程序,但是具有远程控制功能,通常杀毒软件是无法查出它来的,请先确定该服务是否是你自己开放并且是必需的。如果不是请关闭它。
    方法: 请在开始-->运行中输入cmd,然后cd C:\winnt\system32(你的系统安装目录),输入r_server.exe /stop后按回车。然后再输入r_server /uninstall /silence,到C:\winnt\system32(系统目录)下删除r_server.exe admdll.dll radbrv.dll三个文件
           139端口的关闭
    139端口是NetBIOS Session端口,用来文件和打印共享
    方法: 在“网络和拨号连接”中“本地连接”中选取“Internet协议(TCP/IP)”属性,进入“高级TCP/IP设置”“WINS设置”里面有一项“禁用TCP/IP的NETBIOS”,打勾就关闭了139端口。
    对于个人用户来说,可以在各项服务属性设置中设为“禁用”,以免下次重启服务也重新启动,端口也开放了。
           113端口木马的清除
    这是一个基于irc聊天室控制的木马程序。
    1.首先使用netstat -an命令确定自己的系统上是否开放了113端口。
    2.使用fport命令察看出是哪个程序在监听113端口。
    例如我们用fport看到如下结果:
    Pid Process Port Proto Path\system32\vhos.exe
    我们就可以确定在监听在113端口的木马程序是vhos.exe而该程序所在的路径为c:\winnt\system32下。
    3.确定了木马程序名(就是监听113端口的程序)后,在任务管理器中查找到该进程,并使用管理器结束该进程。
    4.在开始-运行中键入regedit运行注册表管理程序,在注册表里查找刚才找到那个程序,并将相关的键值全部删掉。
    5.到木马程序所在的目录下删除该木马程序。(通常木马还会包括其他一些程序,如rscan.exe、psexec.exe、ipcpass.dic、ipcscan.txt等,根据木马程序不同,文件也有所不同,你可以通过察看程序的生成和修改的时间来确定与监听113端口的木马程序有关的其他程序)
    6.重新启动机器。
         限制端口的方法
    对于个人用户来说,您可以限制所有的端口,因为您根本不必让您的机器对外提供任何服务;而对于对外提供网络服务的服务器,我们需把必须利用的端口(比如WWW端口80、FTP端口21、邮件服务端口25、110等)开放,其他的端口则全部关闭。
    1、右键点击“网上邻居”,选择“属性”,然后双击“本地连接” ,弹出“本地连接状态”对话框。
      2、点击[属性]按钮,弹出“本地连接属性”,选择“此连接使用下列项目”中的“Internet协议(TCP/IP)”,然后点击[属性]按钮。
      3、在弹出的“Internet协议(TCP/IP)”对话框中点击[高级]按钮。在弹出的“高级TCP/IP设置”中,选择“选项”标签,选中“TCP/IP筛选”,然后点击[属性]按钮。
      4、在弹出的“TCP/IP筛选”对话框里选择“启用TCP/IP筛选”的复选框,然后把左边“TCP端口”上的“只允许”选上
      这样,您就可以来自己添加或删除您的TCP或UDP或IP的各种端口了。
    添加或者删除完毕,重新启动机器以后,您的服务器就被保护起来了。
    最后提醒,如果您只上网浏览的话,可以不添加任何端口。但是要利用一些网络联络工具,比如OICQ的话,就要把“4000”这个端口打开,同理,如果发现某个常用的网络工具不能起作用的时候,请搞清它在您主机所开的端口,然后在“TCP/IP筛选”中添加端口即可。
  • 你必须学会的几个常用网络测试命令

    annayin 发布于 2007-03-08 10:09:39Digest 3

    如果你是一个网络维护人员,那么肯定要经常处理网络故障,了解和掌握下面几个命令将会有助于您更快地检测到网络故障所在,从而节省时间,提高效率。

      Ping

      Ping是测试网络联接状况以及信息包发送和接收状况非常有用的工具,是网络测试最

      常用的命令。Ping向目标主机(地址)发送一个回送请求数据包,要求目标主机收到请求后给予答复,从而判断网络的响应时间和本机是否与目标主机(地址)联通。

      如果执行Ping不成功,则可以预测故障出现在以下几个方面:网线故障,网络适配器配置不正确,IP地址不正确。如果执行Ping成功而网络仍无法使用,那么问题很可能出在网络系统的软件配置方面,Ping成功只能保证本机与目标主机间存在一条连通的物理路径。

      命令格式:

      ping IP地址或主机名 [-t] [-a] [-n count] [-l size]

      参数含义:

      -t不停地向目标主机发送数据;

      -a 以IP地址格式来显示目标主机的网络地址 ;

      -n count 指定要Ping多少次,具体次数由count来指定 ;

      -l size 指定发送到目标主机的数据包的大小。

      例如当您的机器不能访问Internet,首先您想确认是否是本地局域网的故障。假定局域网的代理服务器IP地址为202.168.0.1,您可以使用Ping避免202.168.0.1命令查看本机是否和代理服务器联通。又如,测试本机的网卡是否正确安装的常用命令是ping 127.0.0.1。

      Tracert

      Tracert命令用来显示数据包到达目标主机所经过的路径,并显示到达每个节点的时间。命令功能同Ping类似,但它所获得的信息要比Ping命令详细得多,它把数据包所走的全部路径、节点的IP以及花费的时间都显示出来。该命令比较适用于大型网络。

      命令格式:

      tracert IP地址或主机名 [-d][-h maximumhops][-j host_list] [-w timeout]

      参数含义:

      -d 不解析目标主机的名字;

      -h maximum_hops 指定搜索到目标地址的最大跳跃数;

      -j host_list 按照主机列表中的地址释放源路由;

      -w timeout 指定超时时间间隔,程序默认的时间单位是毫秒。

      例如大家想要了解自己的计算机与目标主机
    www.cce.com.cn之间详细的传输路径信息,可以在MS-DOS方式输入tracertwww.cce.com.cn。

      如果我们在Tracert命令后面加上一些参数,还可以检测到其他更详细的信息,例如使用参数-d,可以指定程序在跟踪主机的路径信息时,同时也解析目标主机的域名。

      Netstat

      Netstat命令可以帮助网络管理员了解网络的整体使用情况。它可以显示当前正在活动的网络连接的详细信息,例如显示网络连接、路由表和网络接口信息,可以统计目前总共有哪些网络连接正在运行。

      利用命令参数,命令可以显示所有协议的使用状态,这些协议包括TCP协议、UDP协议以及IP协议等,另外还可以选择特定的协议并查看其具体信息,还能显示所有主机的端口号以及当前主机的详细路由信息。

      命令格式:

      netstat [-r] [-s] [-n] [-a]

      参数含义:

      -r 显示本机路由表的内容;

      -s 显示每个协议的使用状态(包括TCP协议、UDP协议、IP协议);

      -n 以数字表格形式显示地址和端口;

      -a 显示所有主机的端口号。

      Winipcfg

      Winipcfg命令以窗口的形式显示IP协议的具体配置信息,命令可以显示网络适配器的物理地址、主机的IP地址、子网掩码以及默认网关等,还可以查看主机名、DNS服务器、节点类型等相关信息。其中网络适配器的物理地址在检测网络错误时非常有用。

      命令格式:

      winipcfg [/?] [/all]

      参数含义:

      /all 显示所有的有关IP地址的配置信息;

      /batch [file] 将命令结果写入指定文件;

      /renew_ all 重试所有网络适配器;

      /release_all 释放所有网络适配器;

      /renew N 复位网络适配器 N;

      /release N 释放网络适配器 N。

      在Microsoft的Windows 95及其以后的操作系统中,都可以运行以上命令。
  • [论坛] 网络性能瓶颈测试

    charmer 发布于 2007-01-16 11:56:49

     

    最近想做个网络性能方面的测试,不知道大家有什么好的建议,把你们的经验共享出来,我想我会在这次测试中用到的工具是:LR(压力方面,虚拟人数(比如10/50/100/200/300/500用户等),性能方面数据收集,带宽获取)、sniffer(主要是得到系统究竟采用了哪些相关的协议、端口、传输的数据等等),在这里带宽可以通过网卡来设置成10M,10M/100M以及100M等模式。

    大家建议建议下啊……

  • 比较全面的测试面试题(技术 人力)--转

    mcfnhm 发布于 2010-10-21 15:58:08

    一套比较完整的软件测试人员面试题(包括技术和人力资源方面)
    你为什么选择软件测试行业
    因为之前有了解软件测试这个行业,觉得他的发展前景很好。也对

    根据你以前的工作经验描述一下软件开发、测试过程,由那些角色负责,你做什么
    要有架构师、开发经理、测试经理、程序员、测试员

    我在里面主要是负责所分到的模块执行测试用例。

    结合你以前的学习和工作经验,你认为如何做好测试。
    根据我以前的工作经验,我认为做好工作首先要有一个好的沟通,只有沟通无障碍了,才会有好的协作,才会有跟好的效率,再一个就是技术一定要过关,做测试要有足够的耐心,和一个良好的工作习惯,不懂的就问,实时与同事沟通这样的话才能做好测试工作。

    你觉得测试最重要的是什么

    尽可能的找出软件的错误

    怎样看待加班问题

    加班的话我没有太多的意见,但是我还是觉得如果能够合理的安排时间的话,不会有太多时候会加班的。

    如果一个很有个性的程序员认为自己的BUG不是BUG,怎么解决?

    首先我要确定我所提的在我认为是不是bug,如果我认为是的话我会在他面前重现这个bug和他讲这是个bug,和他沟通,或者我会找到我的直系领导让他解决。
    为什么在团队中要有测试
    因为软件有错误,如果没有专业的测试人员很难发现软件的一些错误。

    在测试时代学习自己最大的收获是什么?
    在测试时代我除了学习了测试的知识外,还看到了老师们对待测试的一种态度,明白了做任何工作都要有沟通,做测试的也要有很好的沟通才可以做好。知道自己在项目组中的位置,和开发的关系。

    你对未来的规划

    我想在工作中慢慢的积累经验,使自己强大起来,能够担任更重要的职务。

    自己优势及缺点

    我的优点是有足够的耐心对待每一件事情,善于观察事物,承受压力的能力很强。缺点可能就是我不是很爱说话,习惯做不习惯说,但是和人沟通还是没有问题的。

    你为什么选择测试时代不选择51testing

    因为相对比来看测试时代价钱相对公道,师资也不错,还有一个原因就是在网上查了一下测试时代的口碑不错,也是网放心过来的原因。

    13.请谈谈您对测试工作的理解

    我认为测试工作是找出软件产品的错误,

    14.你认为测试人员需要具备哪些素质?

    我认为做测试的应该要有一定的协调能力,因为测试人员要经常与开发接触处理一些问题,如果处理不好的话会引起一些冲突这样的话工作上就会做不好。还有测试人员要有一定的耐心,有的时候做的测试很枯燥乏味的。除了要有耐心之外还要细心,不放过每一个可能的错误。

    15.你为什么能够做测试这一行。

    虽然说我的测试技术还不是很纯熟,但是我觉得我还是可以胜任软件测试这个工作的,因为做软件测试不仅是要求技术好,还要有一定的沟通能力,耐心、细心等外在的因素。综合起来看我认为我是胜任这个工作的。

    1测试的目的是什么?

    测试的目的是找出软件产品中的错误,是软件尽可能的符合用户的要求。

    当软件测试是不可能能够找出全部的错误的。

    2. 测试分为那几个阶段?

    一般来说测试大体分为5个阶段:

    单元测试、集成测试、确认测试、系统测试、验收测试

    在测试过程中如果有需要还要进行回归测试。

    3. 单元测试的测试对象,目的、测试依据、测试方法?

    测试对象是模块内部的程序错误;目的是消除局部模块逻辑和功能上的错误和缺陷;

    测试依据是模块的详细设计;测试方法采用白盒测试

    4. 集成测试的测试对象,目的、测试依据、测试方法?

    集成测试的测试对象是模块间的组装和调用关系;

    目的是找出与软件设计相关的程序结构模块调用关系,模块间接口方面问题;

    测试依据是概要设计;测试方法采用灰盒测试。

    5. 系统测试的测试对象,目的、测试依据、测试方法?

    系统测试的测试对象是整个系统;测试的目的是对整个系统进行测试;

    测试的依据是需求规格说明书;测试方法黑盒测试

    6. 测试覆盖的类型

    测试覆盖的类型有:语句覆盖、判定覆盖、条件覆盖、判定/条件覆盖、条件组合覆盖、路径覆盖

    7.性能测试的分类

    分为:性能测试、负载测试、压力测试、容量测试

    负载测试与压力测试可以结合进行。

    8. 列举您熟悉的主流自动化测试工具

    我熟悉的自动化测试工具有:基于web的测试管理工具TestDirector、配置管理工具VSS、

    QTP以及性能测试工具LoadRunner

    9. 编辑sql语句时,年月日型时间字段如何表达

    加引号

    13. c/s和b/s结构的软件进行测试时有何不同

    C/S又称Client/Server或客户/服务器模式。服务器通常采用高性能的PC、工作站或小型机,并采用大型数据库系统。客户端需要安装专用的客户端软件。

    B/S是Brower/Server的缩写,客户机上只要安装一个浏览器(Browser)。浏览器通过Web Server 同数据库进行数据交互。
    $o;~k V*O
    lTestAge 中国软件测试时代$I siX_ k

    14.安全测试的后台是什么

    17. 页面中有一个输入日期的输入框和一个输入身份证号的输入框,如何进行用例设计?

    输入日期的输入框要考虑边界值、输入非法数据、非数字等

    省份证输入框要考虑18位省份证、16位身份证、非18、16位的数据、汉字、字母、非法数据、

    18. 测试和质量保证有什么区别 你的看法

    质量保证是对软件制作过程的制作质量进行管理,看是否符合公司的规定。

    软件测试是对软件产品的质量本身进行测试,是从技术方面出发测试软件质量

    19. 用过什么缺陷管理工具? 流程是什么 有什么能改进的

    我所熟悉的是TD

    流程是讲测试计划、方案、测试用例录入TD,在TD上执行测试用例记录缺陷,并对bug进行跟踪。

    20. 你有没有用过QTP做项目,QTP的工作原理

    我有用QTP做过项目

    QTP的工作原理是执行重复的手动测试,

    首先制定测试计划再根据测试计划创建测试脚本,然后对脚本进行优化增强测试脚本的能接下来运行脚本分析测试的结果

    21. 什么是白盒测试?白盒测试的工具有哪些?

    白盒测试是测试人员利用程序内部的逻辑结构及有关信息,设计或选择测试用例,对程序所有的逻辑路径进行测试。

    工具有:RationalPurify 、Rational Quantify 、Rational Purecoveage

    22. 路由器,集线器,交换机的区别?

    路由器的作用是用于连接不同网段并且找到网络中数据传输最合适的路径。

    集线器的作用是将一些pc机连起来组成一个局域网。

    交换机的作用与集线器的相似,区别在于集线器采用的是共享带宽的方式,交换机是独享带宽。

    24. 我手上这支笔,请你根据这支笔设计测试用例

    首先我要测它的外观、颜色是否符合要求、她所占的空间是多大、是否环保、接下来测它的质量、这支笔是否能够写字流畅、写出的自得颜色是否符合要求、能使用多长时间等

    25. BUG报告包括那些内容

    Bug出现的位置、可重现的步骤、所使用的数据、bug的截图、发现人及日期。

    26. 请列举一些Oracle数据库中的SID语句

    27. W和H模型的区别

    W模型强调的是测试伴随整个软件开发周期,而且测试的对象不仅是程序,需求也需要进行测试,测试与开发是同步进行的。

    H模型是讲测试活动玩却的独立出来,形成了完全独立的流程,可以实现迭代而W模型不支持迭代这是两者最打的区别。

    28. 没有任何说明书,如何进行测试?

    首先是通过对软件测使用来熟悉整个软件,接着是与开发沟通掌握软件的特性并一一记录下来,作为测试的依据。

    29. 测试计划包括那些内容那些重要?

    测试计划包括


  • 面试前的准备工作

    xin_晴 发布于 2010-10-19 17:02:26

    不管你是通过投简历、写求职信或经人推荐获得了面试机会,你都应该意识到,在全部求职过程中,面试是最具决定性的部分。

    如果以一百分来计算重要性,前面开路的工作占到十分,面试恐怕要占到九十分。

    但是,我还有另一种看法:如果你要在面试中发挥十分,你就要在面试前做出九十分的努力。面试时的临场表现不过是浮出水面的冰山一角。

    我们讲到了大量雇主调查的方式,不再赘述,这些可能要花掉你几十数百倍于面试的时间,只有做过扎实的努力,你才能自信、从容地走进面试现场。

    那么,作为临阵磨枪的方法,你还需要在确定获得面试机会后做哪些准备呢?

    第一,   你需要打扮自己。

    面试过程中,常常在前几秒的印象就能让雇主决定要不要你,虽然他在尽力挣扎,第一印象还是深刻影响着他的潜意识。

    怎么打扮自己呢?至少你要做到干净整洁,最好还有点职业化。对于面试投资银行或者广告公司,职业化的要求可能大不相同,但是你应当尽量去了解这个行当的一般着装要求。

    一个相当聪明的主意是,去你要面试的大厦附近随便转转,看看人们(尤其是挂着你要去面试的公司胸牌的工作人员)一般是怎样的着装风格,照着差不多去做就好了。

    我记得有些来面试新东方的人西装革履,当他们走进办公区的时候,其实是有些不自在的,因为很容易被发现是新来的面试者,如果大家着装很随意,只有你那么闪亮,是会带来格外压力的,让你显得有些呆头呆脑。

    当然,如果你实在搞不清状况,尽量保守、正式一点是不错的;但你最好事前去看看,也可以熟悉一下路线,避免当天由于搞不清路况而迟到等等。

    第二,了解面试的基本步骤。

    如果人力资源部或是什么人打电话给你,叫你去参加面试,顺便问问面试的步骤,面试官的身份、称呼是不会失礼的,还显得你很有心。

    很多公司的网站甚至会写明他们有怎样的应聘步骤,有几轮笔试、面试等等。对于典型的行业及一些著名的企业,网上还存在着大量的“面经”,读一读也有好处,至少要对面试的框架步骤和基本问题了然在胸。

    第三,准备好你的故事脚本

    不管是怎样五花八门的面试,都至少包含要两个部分:首先是相面,然后是考察你的沟通能力。

    面试当然就是一种相面,看一看你是否可爱,好相处。人在长到一定年龄的时候,就要对自己的面相负责,在你脸上的每一条皱纹其实都能说明些什么。他们会用自己的经验看出你是不是会跟他们成为一路人,此外并没有什么,但其实过美或过丑在一般公司都不是什么好事。

    在沟通的过程中,你会讲一些故事来说明自己的某种能力,虽然这些事情是真实发生过的,但最好还是做一些脚本,以便更流畅顺利地表达。讲故事的能力非常重要,这一点在你以后的工作中会不断加深体会。

    第四,准备好可能用到的其他素材。

    在很多公司里,可能会让你就新近发生的事件做一些专业上的评论,因此也应该准备一些素材、数据等等。如果你的话题很老套,论述空泛而缺乏依据,都是非常不利的事情。

    自我介绍这样简单的东西很多人都搞不定,别具一格又跟公司要求比较切题的自我介绍都是少之又少,你会想:这些来面试的家伙都在想些什么,一段枯燥无聊的自我介绍会让面试官恨不得马上把你轰出门外。

    第五,找到面试中可能的亮点。

    有些人真的可能是在面试中闪亮了一下,然后就接近被录取了。面试有时不是一个冗沓的过程,面试官也不完全靠严格的打分录取人,靠的是惊奇和感动。所以,假如你对这家公司的历史格外熟悉,假如你有过对其产品及服务的特别调查,假如你对这一行当有某些独特的见解,甚至你跟面试官有相同的业余爱好,这些都可能成为临门一脚。

    第六,准备好你自己的问题。

    面试也是一个学习的过程,精心准备你的问题。问问题比回答问题常常更考验一个人的水平。准备好你的问题,要简明、独特并且不是查查资料就可以自己找到答案的东西。这些问题要带有你也是在面试这家公司的态度,又带着向前辈讨教的谦卑。如果你只是提廉价的场面上的问题,会让人瞧不起你,好的公司不爱要那种不看重自身价值的人。

    第七,做好心理建设。

    面试中最大的考验是在心态,你有什么好担忧的,不妨找朋友说出来。有时也不妨与同样求职的战友们相互做一些模拟面试,尤其是小组面试,这些过程有助于你应对面试现场可能的突发情况,提前做好预案。我建议你去面试一下身边的朋友,体会一下考官角度的心情,你只要知道面试官也不那么轻松,自己也就多少能松一口气。

    第八,其他人的补充意见,我目前只想到七点。
  • 软件测试 -- 管理系列 -- (2) 初涉管理

    beyondxiang 发布于 2010-10-24 21:16:42

    软件测试 -- 管理系列 -- (2) 初涉管理


    如果你是个表现优秀有潜力的Tester,或者是你们组的 Base team,部门打算提升你做Lead,你该做哪些准备呢?

    如果你已经做了一段时间的leader ,发现每天的工作不只是固定地接受任务了,责任渐渐变多了,加班已经变成家常便饭,有时候一天下来,感觉没做出什么成就,这时的你,该怎么办呢?

    为什么你管理的项目,感觉任务不是很多,但却特别累,你思考过这个问题吗?

    注:IC=Individual Contributor 


    Why should we change our mindset?

    A tale about Lazy crow

    一只乌鸦坐在树上,整天无所事事。一只小兔子看见乌鸦,就问:“我能像你一样,整天坐在那里什么事也不干吗?”乌鸦答道:“当然啦,为什么不呢?”

    于是,兔子便坐在树下,开始休息。突然,一只狐狸出现了。狐狸跳向兔子并把它吃了。

    不知道大家从这个故事中能得到什么样的启发?

      

    一千个人眼中会有一千种答案 ,切合今天的主题可以这么理解:

    这个故事中,乌鸦是管理者,兔子是执行者。兔子希望做领导者,但是只是单纯的模仿表面的休息,没有站在树上,结果就被吃掉了。

    从我们实际情况出发,你从一个IC,一个Tester转变成一个feature owner 改变的不仅仅是工作内容,工作职责,意识和心态也需要改变,这往往是最重要的。

    所以从ICFeature Owner/Lead, 意识必须要转变,意识不转变,会造成自己仍然去做IC 的工作,自己虽然已经做Feature Owner/Lead, 但还是以IC 的角度和意识去思考问题,做事情。轻者造成自己工作不顺利,很难胜任Feature Owner/Lead 的职位,重者造成项目失败。所以角色,意识必须要转变,这是首要的。

     

    lead 面临的挑战:

    1. 领导意识淡薄

    没有督促员工干活的习惯,分配完了就完了。

    1. 沟通不够

    测试工程师,从领导那里接收到任务,完成后把结果反馈上去,就算完成了。

    作为测试组长,你需要  

    1.      与员工保持日常沟通
    2.      MS Lead 沟通
    3.      DM 沟通
    1.      与其他team 沟通

    3. 视野狭窄

            以纯技术角度来看问题

           eg1: bug 在软件产品当前版本没有被修复,postpone

           eg2:: 公司制度一些规定,向组员传达时。

     

    4.. Lead Responsibility 不明确

          每天仍忙于参与产品的测试;没有做lead 应该做的职责,如:Progress control; Risk control; Quality control …



    What should you change in a project v-team view?

    一个典型的v-team  (微软软件外包典型的组织结构)

    V-team指的是virtual team, 抽象过的组织结构。具体如下表:

    1

    What should we change in project view?

    Contact with Client, you are not only yourself but a company business card

    过去,Tester每天的工作只需要执行完Test Lead分配的任务,跑CaseBug,提交结果给Test lead就可以了。现在角色改变了,作为Lead,需要直接跟客户沟通,此时你代表的是BYS的形象。客户眼中的BYS,就是成百上千的奋战在一线的日夜直接与客户沟通的我们所展示出来的形象。

    - 不管是测试报告,邮件还是电话会议都要专业

    - 整体把握项目,制定计划要合理。

    - 在邮件签名,titleMSN签名,某些文档里加上BYSLogo,时刻宣传公司形象。

    - 当然你所负责的项目的提供的专业服务,交付质量是最过硬的形象

    Co-worker, we are providing service, we are equal.

    在整个V-team中,直接的上下级关系(report to关系)并不多, 大家都是项目组的成员,负责不同的工作内容,是合作关系,大家都是平等的。我们虽然是乙方,但并不代表我们低人一等,我们是提供专业服务的,与客户沟通时应该是不卑不亢的。

    一种极端的例子是: 有些新的Test lead,觉得客户是微软的,讲英文的,马上就觉得自己矮了一截,在与客户沟通的过程中表现出明显的自卑,有问题不敢提不敢问,客户说什么就是什么。在客户提出不合理要求时也一味答应,加大了工作量,给自己造成过大压力。

    - 另一种极端的例子是: 有些Test lead合作的客户可能工作比较繁忙或者比较懒,回复的几封邮件都是不知道或着干脆没有回复, 就觉得客户是个傻子,邮件里会表现出来不屑。这种几封邮件就推断客户不行,从而语气不屑的态度,将会阻碍与客户的下一步沟通,对项目产生负面影响。

    -不可能所有的客户都是理想的客户,对于难缠的客户,要有善于发现别人优点的眼睛。工作中双方地位平等,应不卑不亢。

    Operator --> Owner/Driver

    你从一个执行者,转变成一个管理者,其实说Owner/Driver更恰当,你不再是被动的执行任务,而需要主动的Drive这个test pass的顺利进行。

    - 以前test lead刚当上test lead一段时间之后觉得压力特别大,总是加班,很累,宁愿当普通Tester都不愿意做lead。原来,她每天要与客户沟通交流,管理项目,分配任务。但是对于分配下去的任务又不放心,在收到Test结果后,自己又都去测一遍……

    - 即使你现在已经做了一段时间Lead,看起来没什么问题了,但这里也有几个层次。软件外包的基本形式就是客户发包,我们接包,分解,完成任务,交付结果。一开始客户不放心,只会交给一些低端的简单的执行任务。

    一个层次是,客户发任务,我们被动的执行,只要不漏bug, 不出问题基本上就可以了。这个 Lead做了几年,几个release下来, 却还只是leader

    一个层次是,把自己当做这个产品的owner, 我们主动的学习了解整个流程,积极的参与计划讨论,改进流程,到了什么时间该做什么事情不是等着客户发邮件通知,而是我们主动去问主动去做并让客户了解情况, 这样就是你在Drive这个项目,当你取得了客户的信任,客户会放心将更多更重要更复杂的事情给你做,你有更多的发言权,做好了不仅对个人成长发展有帮助,也能帮助发展业务。

    当然,虽然我们要更加主动积极,但是我们毕竟是乙方,要学会保护自己,我们可以参与讨论,可以提建议,但是不要轻易做决定,决定往往意味着要承担后果。

    Manage a project in the whole product life cycle(plan, assignment, monitor, review, …)

    过去你只需要执行你的Lead分配给你的任务,现在你需要管理这个项目从整个产品生命周期考虑,计划,分配,执行,监督,审查

    Just report issue à investigate issue, report issue with solutions

    这里一个最典型的例子就是 当遇到问题的时候你如何处理?

    有些人可能就是报一个bug,向客户报告问题

    有些人可能要先调查一下

    有些人可能先要判断一下。。。

         调查问题,分析问题,查找问题出现的原因,最后给出相应的解决方案。对于这样的处理,能让客户知道你是在思考的,是努力解决问题的,而不是简单的将问题报告成Bug抛给客户,让客户处理。给客户方便,为客户着想,相信客户会更加的信任我们的团队,也很愿意将更多的项目交给我们。

    Where you are in the team, co-operation

    回到刚才的图(图1),你处于这个项目的什么位置,你扮演了什么的角色,你如何跟不同角色的人 打交道,你如何充分调动利用好resource 以最小的代价高效的完成任务?

    以前有这样的情况,我们的Lead做了这项目12年了,不知道整个项目是什么结构,只知道美国有个Lead,每天给我发任务…,遇到block的问题,如果美国这个Lead block ,自己就无计可施了。

    Client expects continuous improvement, show your outcome appropriately

    这几年软件外包发展迅速,竞争也非常激烈,客户对我们的要求也越来越高。客户会期待我们有持续的进步,我们不仅仅需要做好项目,还需要积极思考如何改进流程,提高效率,而且还要学会适度的展示工作成果。

    举例:

        一个team经过不懈的努力,把自己产品的test case automated 率提高到了90% ,这个数字应该是公认比较高的了,他们team 也认为这个值很高了,没必要继续提高了。但是几个release 下来,客户提出很大的质疑,为什么automation 率一直没提高。

    ---客户期望的是你的工作一直的改进,而不是一直保持不变。

     

    首先判断哪些能说哪些不能说 ,如果要说的话,还要把握好度。

    举例:

     小组1—通过开发自动化测试工具,大大提高了测试效率,缩短了测试周期。将     此回报给客户,客户反而提出要测试团队裁人的要求。

     小组2—通过开发和使用自动化工具,完善测试流程,小组进一步提高了测试效率,缩短了周期,提高了测试质量。在竞争者以低价向客户竞争取该项目,该Team展示他们工作的改进和高效的自动化工具,客户将项目交给了该小组。

    Automation提高效率, manual提高质量,保住项目

    以上我只列出一些我认为最重要的,想要做好项目,提升管理能力,需要注意的远远不止这些……


    What should you change in your company org view? 

    欧美软件外包公司的基本组织结构

    2

    We are part of your company, not MS

    要分清项目之内和项目之外的事情,不同的情况应该找谁

       - 案例一:某员工入职后就Onsite了,一直在微软上班。某天,该员工机器坏了,他拨通了微软manager的电话来解决

       - 请假

    Assist your Manager

    辅佐上级(DM), 准确的传达公司精神,指示

       - 一个敏感的例子,有人离职了,信息传递偏离事实,造成员工对公司的误解。

    执行力

    谁都会听领导的话,但执行力怎么样,每个人都有差异的。举个例子:执行一条公司的规定:每个人都要挂胸卡,你会发现不同的团队执行的效果是不一样的。有的人会想办法,如先发邮件通知,第二天上班的时候再提醒,等等。你会发现,有的小组100%都挂了胸卡,有的则不是。对于执行不到位的团队,你要去问他为什么这么样,可能会得到这样的回复:我说了啊,他们不听。“ 这样的执行力肯定不行。

    Manage your team member

    培养,辅导,激励,管理下属

    问题:为什么要积极培养下属?

    如果你需要调动,如果没有人可以接替Lead的工作,那么Lead就必须首先完成工作交接,从而不能顺利的离开当前的岗位。下属的提高,也有利于提高项目的交付质量,减轻Lead的工作量。

    Leverage internal resources

    学会调用公司内部资源

       - 不会写test plan, 旁边的人写了两年了

       - 问测试经验说不会

       - 遇到问题不会解决,旁边就坐着专家

       - 只要公司有人会的,就可以和客户说会

    举例:微软Itest 调动了,Lead 发邮件慰问, Itest回信:你就像会魔法一样,能把所有难题都解决了。实际上,该Lead coding testing 技术水平都不是很出色,她之所以能解决“所有问题”,关键在于她能充分利用团队的智慧以及公司丰富的资源来处理客户的问题,赢得客户的赞赏。

    Team Building 


    Test Lead responsibilities?

    项目工作:

    计划以及变更管理的安排

    在每个项目(每个release)开始前, 就资源/技术等可能的风险等作评估, 就风险计划和DM以及微软lead做有效沟通

    对于需要写test plan的项目组,test lead和客户沟通完成plan

    在每个项目开始之前,完成项目准备工作(包括人员,机器,系统 等的准备)。

    组内流程/标准建立

    包括各种Template, standard 指导大家如何规范化的开展工作, 以及进度/质量控制流程来保证项目按时完成 。

    建立有效的组织结构和流程。

    自动化组:Automation process and templates setting up BU对于写coding的项目组,test lead负责安排和客户沟通,建立该组的coding specification, code review流程。

    其他测试流程和模板的建立。

    每个项目组有一份自己的bug template指导新人怎么写bug; 对于新人要给予充分的指导,安排有经验的老tester指导检查新人的任务,包括每个bug,写的自动测试脚本等。Test lead负责培训组内人员写测试用例,并安排抽查,纠正写得不好的case

    安排review所有testerdaily report, 确保所有的tester每天按时按质完成了自己的任务;保证项目组每天的工作按时高质交付。

    知识管理和培训

    及时组织项目组培训与经验总结,尤其是在项目间歇期的时候; 根据需要向部门提出培训需求。

    组织tester及时总结项目有关的或其他技术方面的经验,尤其是可以share给全部门的。

    日常其他工作,处理问题,变更管理

    协调解决项目中遇到的问题,提交自己无法解决的工作问题给所属DM 提出问题的时候最好能够提出自己的建议和解决办法。

    帮助tester提高项目问题沟通能力。

    定期组织一次team会议,总结问题和经验形成文档, 安排下一个阶段的工作。

    向微软提交项目进度Daily reportWeekly report。如果DM 要求的话,提交Monthly Report给所属DM

    对于客户临时增加的新任务,test lead负责与客户做好沟通,在组内协调资源保证按期高质量完成。如果需要帮助,及时报告给DM

    人员管理:

    发现人才,培养人才。

    培养下属。发现/培养/推荐有潜力成为技术高手或者管理人才的人员。

    根据组内具体情况为tester组织/申请合适的培训,提供TESTER完成工作和进一步发展所需要的帮助。

    经常与组员沟通,了解组内TESTER的工作能力及特长,对目前工作的满意度,稳定性,个人发展的期望(技术路线,管理路线,其它路线),希望得到的培训等,并就此及时帮助解决或向上一级反映。

    创建良好的team工作氛围,了解并帮助解决TESTER的生活情况和生活中遇到的困难。

    负责对TESTER进行考评, 就考评发现的问题及时与有关tester做沟通。

    协助新tester在试用期的成长,填写试用期考核表和转正审批表。

    其它

    协助部门内部其他辅助小组,部门,公司的一些工作。

    与客户建立良好的关系。

    树立市场意识,及时将扩大市场的相关信息反馈给部门;为部门/公司的进一步发展努力。


  • 如何测试ERP

    duoluohua 发布于 2010-10-03 17:05:58

    如何测试ERP

    测试ERP的难点

    ERP不象汽车、大楼等可以从外观形象判断,也不象电影一样从头看一遍就能判断好与坏,水平高与低

    ERP是立体的互相动态流动和联络,互相之间跑上80%就容易知道好与坏,水平高与低,是否流畅

     

    1.测试ERP表单功能项目是否齐全

    所熟悉的模块出发,检查自己现实中应用的表单种类是不是齐全

    表单内的项目是不是齐全

    表单里的项目的排列是不是符合一般人的操作习惯

    表单里的项目是不是关联到基础资料和相关表单,如客户编码关联到客户资料,进料单关联到采购单

     

    2.测试ERP,从基本的仓库模块测试,以点带面

    编码表的项目齐全性,方便性,以及导入excel表的功能

    输入一张客户订单,注意不输入备注类.看看对库存表中的增加了客户保留数

    测试输入一张采购单,再输入一张进料单,对仓库库存表的影响,增加了在途数,以及相关的查询

    输入领料单,输入负数和超过库存数,查看对库存表的影响

    输入制成品入库单,查看对库存表的影响

    输入出货单,查看对保留数的冲销和对库存数的减少

    测试应付账款,对账单

    测试库存表中的明细进出账,月报表

     

    3.测试ERPMRP功能

    输入一张客户订单并审核

    输入一张生产单并审核

    输入一个2-3BOM,并设置好物料编码的pms采购自制和委外属性

    MRP生产单

    查看采购申请表,制令表,委外制令表,查看库存表中的在途和保留数,以及库存数

    输入一张采购单,并关联采购申请表

    输入进料单并关联采购单,查看库存表中的在途和保留数,以及库存数

    输入领料单,查看库存表中的在途和保留数,以及库存数

    输入制成品入库单,查看库存表中的在途和保留数,以及库存数

    输入出货单,查看库存表中的在途和保留数,以及库存数

     

    4.测试ERP的委外

    1)没有MRP单独使用的情况

    输入委外领料单

    查看委外在途表/欠货表,查看库存表中的配件在途和材料库存数变化

    输入收货单

    查看委外在途表/欠货表,查看库存表中的配件在途和库存数变化

    2)有生产单MRP的情况

    物料编码的配件(下属有1bom)pms属性为S

    客户订单--审核--生产单--审核--MRP

    查看MRP前后库存表中的在途,保留和库存数变化和在途保留的明细

    输入委外领料单

    查看委外在途表/欠货表,查看库存表中的配件在途和材料库存数变化

    输入收货单

    查看委外在途表/欠货表,查看库存表中的在途和库存数变化

     

    5. 测试ERP软件的坚定性

    每种表单都随便输入异常的输入,测试稳定状况,有没有错误检查,以及死机状况,如日期输入2000.18.50

    使用中关闭电脑或者拔掉网线,以及windows进程表中杀掉ERP运行,再重新进入的情况

    不接打印器的状况执行打印功能

    开启多套运行并用多个用户名进入,以及1个用户同时登陆的情况

     

    6.测试ERP的用户权限

    设置群组和用户,包括模块权限,表单只读,创建权,修改权限,单价权限

    一个群中有多个用户

    一个用户属于多个群组

    测试登陆后的权限

    设置用户的登陆限制,时间限制,远程限制,测试登陆

    设置同群组里的修改其他成员,只读其他成员建立的单,并登陆测试

     

    7.测试ERP数据备份和恢复数据

     

    8.测试ERP的应收账款和对账单

     

    9.测试成本表

    仓库月报表

    生产单领用成本

     

    10.测试ERP2次开发的能力

    增加现有系统没有的功能项目,看看多久能做出来以及做出来的品质

     

    11.测试ERP的技术支持能力

    询问模块表单的一些功能和关系

    询问询问表单的异常情况

  • web测试的经典总结

    duoluohua 发布于 2010-10-03 21:15:03

    web测试的经典总结



    基于Web的系统测试
    在基于Web的系统开发中,如果缺乏严格的过程,我们在开发、发布、实施和维护Web的过程中,可能就会碰到一些严重的问题,失败的可能性很大。而且,随着基于Web的系统变得越来越复杂,一个项目的失败将可能导致很多问题。当这种情况发生时,我们对WebInternet的信心可能会无法挽救地动摇,从而引起Web危机。并且,Web危机可能会比软件开发人员所面对的软件危机更加严重、更加广泛。
    Web工程过程中,基于Web系统的测试、确认和验收是一项重要而富有挑战性的工作。基于Web的系统测试与传统的软件测试不同,它不但需要检查和验证是否按照设计的要求运行,而且还要测试系统在不同用户的浏览器端的显示是否合适。重要的是,还要从最终用户的角度进行安全性和可用性测试。然而,InternetWeb媒体的不可预见性使测试基于Web的系统变得困难。因此,我们必须为测试和评估复杂的基于Web的系统研究新的方法和技术。
    一般软件的发布周期以月或以年计算,而Web应用的发布周期以天计算甚至以小时计算。Web测试人员必须处理更短的发布周期,测试人员和测试管理人员面临着从测试传统的C/S结构和框架环境到测试快速改变的Web应用系统的转变。
    一、        功能测试
    1
    、链接测试
    链接是Web应用系统的一个主要特征,它是在页面之间切换和指导用户去一些不知道地址的页面的主要手段。链接测试可分为三个方面。首先,测试所有链接是否按指示的那样确实链接到了该链接的页面;其次,测试所链接的页面是否存在;最后,保证Web应用系统上没有孤立的页面,所谓孤立页面是指没有链接指向该页面,只有知道正确的URL地址才能访问。
    链接测试可以自动进行,现在已经有许多工具可以采用。链接测试必须在集成测试阶段完成,也就是说,在整个Web应用系统的所有页面开发完成之后进行链接测试。
    2
    、表单测试
    当用户给Web应用系统管理员提交信息时,就需要使用表单操作,例如用户注册、登陆、信息提交等。在这种情况下,我们必须测试提交操作的完整性,以校验提交给服务器的信息的正确性。例如:用户填写的出生日期与职业是否恰当,填写的所属省份与所在城市是否匹配等。如果使用了默认值,还要检验默认值的正确性。如果表单只能接受指定的某些值,则也要进行测试。例如:只能接受某些字符,测试时可以跳过这些字符,看系统是否会报错。
    3
    Cookies测试
    Cookies
    通常用来存储用户信息和用户在某应用系统的操作,当一个用户使用Cookies访问了某一个应用系统时,Web服务器将发送关于用户的信息,把该信息以Cookies的形式存储在客户端计算机上,这可用来创建动态和自定义页面或者存储登陆等信息。
    如果Web应用系统使用了Cookies,就必须检查Cookies是否能正常工作。测试的内容可包括Cookies是否起作用,是否按预定的时间进行保存,刷新对Cookies有什么影响等。
    4
    、设计语言测试
    Web
    设计语言版本的差异可以引起客户端或服务器端严重的问题,例如使用哪种版本的HTML等。当在分布式环境中开发时,开发人员都不在一起,这个问题就显得尤为重要。除了HTML的版本问题外,不同的脚本语言,例如JavaJavaScript ActiveXVBScriptPerl等也要进行验证。
    5
    、数据库测试
    Web应用技术中,数据库起着重要的作用,数据库为Web应用系统的管理、运行、查询和实现用户对数据存储的请求等提供空间。在Web应用中,最常用的数据库类型是关系型数据库,可以使用SQL对信息进行处理。
    在使用了数据库的Web应用系统中,一般情况下,可能发生两种错误,分别是数据一致性错误和输出错误。数据一致性错误主要是由于用户提交的表单信息不正确而造成的,而输出错误主要是由于网络速度或程序设计问题等引起的,针对这两种情况,可分别进行测试。
    二、        性能测试
    1
    、连接速度测试
    用户连接到Web应用系统的速度根据上网方式的变化而变化,他们或许是电话拨号,或是宽带上网。当下载一个程序时,用户可以等较长的时间,但如果仅仅访问一个页面就不会这样。如果Web系统响应时间太长(例如超过5秒钟),用户就会因没有耐心等待而离开。
    另外,有些页面有超时的限制,如果响应速度太慢,用户可能还没来得及浏览内容,就需要重新登陆了。而且,连接速度太慢,还可能引起数据丢失,使用户得不到真实的页面。
    2
    、负载测试
    负载测试是为了测量Web系统在某一负载级别上的性能,以保证Web系统在需求范围内能正常工作。负载级别可以是某个时刻同时访问Web系统的用户数量,也可以是在线数据处理的数量。例如:Web应用系统能允许多少个用户同时在线?如果超过了这个数量,会出现什么现象?Web应用系统能否处理大量用户对同一个页面的请求?
    3
    、压力测试
    负载测试应该安排在Web系统发布以后,在实际的网络环境中进行测试。因为一个企业内部员工,特别是项目组人员总是有限的,而一个Web系统能同时处理的请求数量将远远超出这个限度,所以,只有放在Internet上,接受负载测试,其结果才是正确可信的。
    进行压力测试是指实际破坏一个Web应用系统,测试系统的反映。压力测试是测试系统的限制和故障恢复能力,也就是测试Web应用系统会不会崩溃,在什么情况下会崩溃。黑客常常提供错误的数据负载,直到Web应用系统崩溃,接着当系统重新启动时获得存取权。
    压力测试的区域包括表单、登陆和其他信息传输页面等。
    三、        可用性测试
    1
    、导航测试
    导航描述了用户在一个页面内操作的方式,在不同的用户接口控制之间,例如按钮、对话框、列表和窗口等;或在不同的连接页面之间。通过考虑下列问题,可以决定一个Web应用系统是否易于导航:导航是否直观?Web系统的主要部分是否可通过主页存取?Web系统是否需要站点地图、搜索引擎或其他的导航帮助?
    在一个页面上放太多的信息往往起到与预期相反的效果。Web应用系统的用户趋向于目的驱动,很快地扫描一个Web应用系统,看是否有满足自己需要的信息,如果没有,就会很快地离开。很少有用户愿意花时间去熟悉Web应用系统的结构,因此,Web应用系统导航帮助要尽可能地准确。
    导航的另一个重要方面是Web应用系统的页面结构、导航、菜单、连接的风格是否一致。确保用户凭直觉就知道Web应用系统里面是否还有内容,内容在什么地方。
    Web
    应用系统的层次一旦决定,就要着手测试用户导航功能,让最终用户参与这种测试,效果将更加明显。
    2
    、图形测试
    Web应用系统中,适当的图片和动画既能起到广告宣传的作用,又能起到美化页面的功能。一个Web应用系统的图形可以包括图片、动画、边框、颜色、字体、背景、按钮等。图形测试的内容有:
    1)要确保图形有明确的用途,图片或动画不要胡乱地堆在一起,以免浪费传输时间。Web应用系统的图片尺寸要尽量地小,并且要能清楚地说明某件事情,一般都链接到某个具体的页面。
    2)验证所有页面字体的风格是否一致。
    3)背景颜色应该与字体颜色和前景颜色相搭配。
    4)图片的大小和质量也是一个很重要的因素,一般采用JPGGIF压缩。
    3
    、内容测试
    内容测试用来检验Web应用系统提供信息的正确性、准确性和相关性。
    信息的正确性是指信息是可靠的还是误传的。例如,在商品价格列表中,错误的价格可能引起财政问题甚至导致法律纠纷;信息的准确性是指是否有语法或拼写错误。这种测试通常使用一些文字处理软件来进行,例如使用Microsoft Word"拼音与语法检查"功能;信息的相关性是指是否在当前页面可以找到与当前浏览信息相关的信息列表或入口,也就是一般Web站点中的所谓"相关文章列表"
    4
    、整体界面测试
    整体界面是指整个Web应用系统的页面结构设计,是给用户的一个整体感。例如:当用户浏览Web应用系统时是否感到舒适,是否凭直觉就知道要找的信息在什么地方?整个Web应用系统的设计风格是否一致?
    对整体界面的测试过程,其实是一个对最终用户进行调查的过程。一般Web应用系统采取在主页上做一个调查问卷的形式,来得到最终用户的反馈信息。
    对所有的可用性测试来说,都需要有外部人员(与Web应用系统开发没有联系或联系很少的人员)的参与,最好是最终用户的参与。
    四、        客户端兼容性测试
    1
    、平台测试
    市场上有很多不同的操作系统类型,最常见的有WindowsUnixMacintoshLinux等。Web应用系统的最终用户究竟使用哪一种操作系统,取决于用户系统的配置。这样,就可能会发生兼容性问题,同一个应用可能在某些操作系统下能正常运行,但在另外的操作系统下可能会运行失败。
    因此,在Web系统发布之前,需要在各种操作系统下对Web系统进行兼容性测试。
    2
    、浏览器测试
    浏览器是Web客户端最核心的构件,来自不同厂商的浏览器对Java,、JavaScript ActiveX plug-ins或不同的HTML规格有不同的支持。例如,ActiveXMicrosoft的产品,是为Internet Explorer而设计的,JavaScriptNetscape的产品,JavaSun的产品等等。另外,框架和层次结构风格在不同的浏览器中也有不同的显示,甚至根本不显示。不同的浏览器对安全性和Java的设置也不一样。
    测试浏览器兼容性的一个方法是创建一个兼容性矩阵。在这个矩阵中,测试不同厂商、不同版本的浏览器对某些构件和设置的适应性。
    五、        安全性测试
    Web
    应用系统的安全性测试区域主要有:
    1)现在的Web应用系统基本采用先注册,后登陆的方式。因此,必须测试有效和无效的用户名和密码,要注意到是否大小写敏感,可以试多少次的限制,是否可以不登陆而直接浏览某个页面等。
    2Web应用系统是否有超时的限制,也就是说,用户登陆后在一定时间内(例如15分钟)没有点击任何页面,是否需要重新登陆才能正常使用。
    3)为了保证Web应用系统的安全性,日志文件是至关重要的。需要测试相关信息是否写进了日志文件、是否可追踪。
    4)当使用了安全套接字时,还要测试加密是否正确,检查信息的完整性。
    5)服务器端的脚本常常构成安全漏洞,这些漏洞又常常被黑客利用。所以,还要测试没有经过授权,就不能在服务器端放置和编辑脚本的问题。
    六、总结
    本文从功能、性能、可用性、客户端兼容性、安全性等方面讨论了基于Web的系统测试方法。
    基于Web的系统测试与传统的软件测试既有相同之处,也有不同的地方,对软件测试提出了新的挑战。基于Web 查看(378) 评论(0) 收藏 分享 管理

  • RFT的两种校验方法之介绍和比较

    jiangbuhai 发布于 2007-06-13 17:30:20

    RFT的两种校验方法之介绍和比较

     

    我们在做自动化测试时,会需要验证页面上某些值是否是我们所期望的预期值,我们把它称为校验点。RFT有两种校验点:一种称为静态的校验点,另一种成为动态的校验点。

     

    首先,介绍一下静态校验点,静态校验点的方法很简单,和原来我们用ROBOT时差不多,是在代码里写好校验点所在的窗口,校验点控键的类型和校验点在代码中的名称。然后让工具通过这些条件到网页上找到该校验点,然后再比较校验点里的值是否和我们预期的值相等。

     

    其次,再来介绍动态校验点,动态校验点的方法相对于上述方法来说,要复杂多了。它的思想是这样的,把验证点的预期值和验证点的描述放在两个资源文件里,当调用这个验证方法的时候,会把页面上的包含所有验证点的控键容器,作为一个参数传到方法里,然后这个方法通过调用资源文件,搜索容器中符合验证点描述的控键,再把其值取出和预期值进行比较。

      

     

    最后,这两种方法之比较,见下表:

     

     

     

    静态测试方法

    动态测试方法

    预期值

    硬编码于源程序中

    配置在一个单独的文件中

    被测试控件

    需要一个个的抓取到scrīpt explorer

    配置在一个单独的文件中

    校验代码

    非常冗长,代码行和校验点数量成正比

    非常简短,而且随着校验点增加而不变

    维护性

    需要在编译前修改源程序,而且经常需要维护scrīpt explorer

    只需要修改两个配置文件,不需要重新编译,几乎不需要维护scrīpt explorer

    重用性

    几乎没有重用性,对于新增加的校验点,需要添加新的程序段

    重用性非常高,不需要对新增的校验点不需要编写任何新的代码

    性能

    性能非常好

    性能中等,因为遍历需要消耗时间

     

    在前面提到,在动态的测试框架下,如果需要进行回归测试,或者增加/减少被测试控件,只需要修改两个配置文件并且重新运行即可。在这个过程中,预期值、测试过程和被测试对象之间的耦合被大量减少,带来的是代码可读性和可维护性的提高。然而,该方法也是以损失一部分性能为代价的,因为对象的动态识别需要至少两次遍历tabContent内部的所有对象,这就损失了一些效率。幸运的是,对于大多数基于eclipse的被测试程序,根据实践经验用户通常感觉不到这方面性能的问题。

     

    动态的校验点测试的另外一个巨大的潜力在于,它有潜力发展成为一种校验点测试的框架。测试人员使用自动化测试工具来进行测试,其本质目的是为了能够减少手工重复点击和校验,所以测试人员书写的代码脚本越少越少。将测试人员关注的业务部分单独配置出来,而将他们不熟悉的部分封装在一个框架中,会大大提高测试工作的有效性。而本文提供的动态校验点测试正是在这个方面做出了一定的探索。在这个基础上,再增加配置文件的管理、多种控件/相对位置的识别,再辅之于输入输出的接口,它就可能是一个通用性很强的RFT测试框架。

     

    附:以CWT员工管理为例,说明两种种验证点方法的核心代码

    1.静态验证点判断方法:

    boolean result=staffpw.equals(text_staffPassword2().getText());//判断字符串是否等于预期值

    String context="The value of textfield ="+staffpw;

    RationalTestscrīpt.logTestResult(context,result);//输出测试的结果

           

    3.动态验证点判断方法:

    //该类负责主要的校验流程和关键参数的传入

    public class PanelVerifier {

       

        private TestObject tabContent = null; // 控件容器的引用

     

        private String dataPath = null; // 预期值文件和控件定义文件的存储位置

     

        public PanelVerifier(String dataPath, TestObject tabContent) {

            this.tabContent = tabContent;

            this.dataPath = dataPath;

        }

     

        private List readProperties() throws Exception {

            /**

             * 然后,添加方法readProperties来读取配置文件。readProperties方法读

             * 取预期值文件和控件定义配置文件,将这些读取的值封装在一个List中,List

             * 的每个元素都是ObjDef的实例。每个ObjDef对应于一个被测试的控件对象,其中的各种属性值都来自于配置文件。

             */

            Map propertiesMap=readAllProperties();

            List lst = new ArrayList();

            try {

                Set set = propertiesMap.keySet();

                Iterator iter = set.iterator();

                while (iter.hasNext()){

                    Object obj1 = iter.next();

                    System.out.println(obj1 + "::" + propertiesMap.get(obj1));

                    String[] str = propertiesMap.get(obj1).toString().split(",");

                    ObjDef ōbj = new ObjDef();

                    obj.setInput(str[0]);

                    obj.setLabel(str[1]);

                    obj.setPos(str[2]);

                    obj.setType(str[3]);

                    lst.add(obj);

                }

            } catch(Exception e) {

                e.printStackTrace();

            }  

          

            return lst;

           

        }

     

        public Map readAllProperties() throws Exception {

            Properties p = new Properties();

            Map propertiesMap = new HashMap();

            File file = new File(dataPath + IConstant.IDSFILE);

       

            p.load(new FileInputStream(file));

     

            loadProperties(p, propertiesMap);//propertiesMap:{staffEmail=seasy@etraveltek.com, staffName=seasy, staffRPW=123, staffPW=123}

            System.out.println(propertiesMap);

            file = new File(dataPath + IConstant.OBJECTSFIlE);

            p.load(new FileInputStream(file));

            loadProperties(p, propertiesMap);//propertiesMap:{staffEmail=seasy@etraveltek.com,.tag,Text, staffName=seasy,.tag,Text, staffRPW=123,.tag,Text, staffPW=123,.tag,Text}

            System.out.println(propertiesMap);

            return propertiesMap;

        }

     

        private void loadProperties(Properties p, Map propertiesMap) {

            Set pSet = p.keySet();

            Iterator iter = pSet.iterator();

     

            while (iter.hasNext()) {

                Object key = iter.next();

                String value = p.getProperty(key.toString());

                setMapValue(propertiesMap, key, value);

            }

        }

     

        private void setMapValue(Map map, Object key, Object value) {

            Object beforeValue = map.get(key);

            if (beforeValue == null) {

                map.put(key, value);

            } else {

                map.put(key, beforeValue.toString() + "," + value.toString());

            }

        }

     

        /**

         * 接下来,为类PanelVerifier增加一个filterSubitems方法,该方法能够 在一个被测试对象内部寻找属性符合预期的子对象。比如

         * filterSubitems(tabcontent, "text","Name"),就是在

         * tabcontent的所有子对象中寻找符合属性text等于Name的子对象。

         */

        private List filterSubitems(ExtTestObject testobject, String propertyname,

                Object propertyvalue,Object lablevalue) {

            TestObject[] children = testobject.getTestObject().getChildren();

            ArrayList list = new ArrayList();

            for (int i = 0; i < children.length; i++) { // 循环遍历所有内部的被测试对象

                TestObject subitem = children[i];

    //          System.out.println(subitem.getProperties());

                ExtTestObject eto = new ExtTestObject(subitem);

                try {

                    Object value1 = subitem.getProperty(propertyname);

                    Object value2 = subitem.getProperty(".name");

                    if (value1 != null && value1.equals(propertyvalue) && value2 != null && value2.equals(lablevalue) ) { // 判断对象是否符合要求

                        list.add(eto);

                    }

                } catch (Exception e) {

     

                }

                list.addAll(filterSubitems(eto, propertyname, propertyvalue,lablevalue));

            }

            return list;

        }

     

        public void verify() throws Exception {

            List expectvalue = readProperties();

           

            for (int i = 0; i <expectvalue.size(); i++)

            {

                ObjDef ōbj = (ObjDef) expectvalue.get(i);

                List factvalue = filterSubitems(new ExtTestObject(tabContent),obj.getPos(),obj.getType(),obj.getLabel());

                boolean flag=false;

                String value = "";

                for (int j = 0; j < factvalue.size(); j++)

                {

                    ExtTestObject eto = (ExtTestObject) factvalue.get(j);

                    value = (String) eto.getTestObject().getTestData("text")

                            .getProperty("data");

                    boolean result = value.equals(obj.getInput());

                    if (result)

                    {

                        RationalTestscrīpt.logTestResult(

  • 用LoadRunner监控windows、linux、UNIX、IBM AIX机器的性能

    wangyong3552128 发布于 2007-09-25 13:09:25

    LR监控windowslinux、UNIX、IBM AIX系统方法

     

    一、监控windows系统:
    1
    、监视连接前的准备工作
            1
    )进入被监视windows系统,开启以下二个服务Remote Procedure Call(RPC) Remote Registry Service (开始—)运行 中输入services.msc,开启对应服务即可)
            2
    )在被监视的WINDOWS机器上:右击我的电脑,选择管理->共享文件夹->共享 在这里面要有C$这个共享文件夹 (要是没有自己手动加上)
            3
    )在安装LR的机器上,开始》运行,输入 \\被监视机器IP\C$ 然后输入管理员帐号和密码,如果能看到被监视机器的C盘了,就说明你得到了那台机器的管理员权限,可以使用LR去连接了。(LR要连接WINDOWS机器进行监视要有管理员帐号和密码才行。)
       
    问题:在执行步骤3)时,输入 \\被监视机器IP\C$,出现不能以administrator身份访问被监控系统(若采用这种方式用LR对其监控的话,会提示:找不到网络路径)的情况,现象就是用户名输入框是灰色的,并且默认用户是guest
       
    解决办法:这是安全策略的设置问题(管理工具 -> 本地安全策略 -> 安全选项 -> "网络访问:本地帐户的共享和安全模式")。默认情况下,XP的访问方式是"仅来宾"的方式,如果你访问它,当然就固定为Guest来访问,而guest账户没有监控的权限,所以要把访问方式改为经典模式,这样就可以以administrator的身份登陆了。修改后,再次执行步骤3),输入管理员用户名和密码,就可以访问被监控机器C盘了
       
    若这样都不行的话(可能是其它问题引起的),那只好采取别的方法了。在服务器的机子上,通过windows自带的性能日志和警报下的计数器日志中新增加一个监控日志(管理工具性能性能日志和警报),配置好日志,也能监控服务器的cpumemorydisk等计数器。当然,这种方法就不是用LR来监控了。

    2
    、用LR监视windows的步骤
       
    controller 中,Windows Resources窗口中右击鼠标选择Add Measurements,添加被监控windowsIP地址,选择所属系统,然后选择需要监控的指标就可以开始监控了。

    二、监控linux
    1
    准备工作
       
    可以通过两种方法验证服务器上是否配置了rstatd守护程序:
       
    使用rup命令,它用于报告计算机的各种统计信息,其中就包括rstatd的配置信息。使用命令rup 10.130.61.203,此处10.130.61.203是要监视的linux/Unix服务器的Ip,如果该命令返回相关的统计信息。则表示已经配置并且激活了rstatd守护进程;若未返回有意义的统计信息,或者出现一条错误报告,则表示rstatd守护进程尚未被配置或有问题。
       
    使用find命令
    #find / -name rpc.rstatd,
    该命令用于查找系统中是否存在rpc.rstatd文件,如果没有,说明系统没有安装rstatd守护程序。
       
    如果服务器上没有安装rstatd程序(一般来说LINUX都没有安装),需要下载一个包才有这个服务,包名字是rpc.rstatd-4.0.1.tar.gz. 这是一个源码,需要编译,下载并安装rstatd(可以在http://sourceforge.net/projects/rstatd这个地址下载)
    下载后,开始安装,安装步骤如下:
    tar -xzvf  rpc.rstatd-4.0.1.tar.gz
    cd  rpc.rstatd-4.0.1/
    ./configure  —
    配置操作
    make —
    进行编译
    make install —
    开始安装
    rpc.rstatd —
    启动rstatd进程

    2
    )安装完成后配置rstatd 目标守护进程xinetd,它的主配置文件是/etc/xinetd.conf ,它里面内容是一些如下的基本信息:
    #
    # xinetd.conf
    #
    # Copyright (c) 1998-2001 SuSE GmbH Nuernberg, Germany.
    # Copyright (c) 2002 SuSE Linux AG, Nuernberg, Germany.
    #
    defaults
    {
            log_type        = FILE /var/log/xinetd.log
            log_on_success  = HOST EXIT DURATION
            log_on_failure  = HOST ATTEMPT
    #        only_from       = localhost
            instances       = 30
            cps             = 50 10
    #
    # The specification of an interface is interesting, if we are on a firewall.
    # For example, if you only want to provide services from an internal
    # network interface, you may specify your internal interfaces IP-Address.
    #
    #       interface       = 127.0.0.1
    }
    includedir /etc/xinetd.d

    我们这里需要修改的是/etc/xinetd.d/下的三个conf文件 rlogin ,rsh,rexec 这三个配置文件,打这三个文件里的disable = yes都改成 disable = no ( disabled 用在默认的 {} 中 禁止服务)或是把# default: off都设置成 on 这个的意思就是在xinetd启动的时候默认都启动上面的三个服务!
      
    说明:我自己在配置时,没有disable = yes这项,我就将# default: off改为:default: on,重启后(cd /etc/init.d/     ./xinetd restart)通过netstat -an |grep 514查看,没有返回。然后,我就手动在三个文件中最后一行加入disable = no,再重启xinetd,再使用netstat -an |grep 514查看,得到tcp 0 0 0.0.0.0:514 0.0.0.0:* LISTEN结果,表明rsh服务器已经启动。


         
    只要保证Linux机器上的进程里有rstatdxinetd这二个服务就可以用LR去监视了
    两点小的技巧:
    检查是否启动: rsh server 监听的TCP 514

    [root@mg04 root]# netstat -an |grep 514
    tcp 0 0 0.0.0.0:514 0.0.0.0:* LISTEN
    如果能看到514在监听说明rsh服务器已经启动。
    检查是否启动: rstatd
    输入命令
    : rpcinfo -p
    如果能看到类似如下信息:

    程序     版本 协议  端口
    100001    5   udp    937  rstatd
    100001    4   udp    937  rstatd
    100001    3   udp    937  rstatd
    100001    2   udp    937  rstatd
    100001    1   udp    937  rstatd
    那就说明rstatd服务启动了,(当然这里也可以用ps ax代替)
    重起xinetd方法:

    suse linux如下操作:
    cd /etc/init.d/
    ./xinetd restart
    看到网上有的地方说使用如下命令:
    # service xinetd reload
    # /sbin/service xinetd rstart
    不知道是在什么系统用的。
    安装rsh,和rsh-server两个服务包方法
    a.
    卸载
    rsh
    # rpm –q rsh----------
    查看版本号

    # rpm -e
    版本号---------卸载该版本。

    b
    .安装

    # rpm –ivh rsh-0.17-14.i386.rpm rsh-server-0.17-14.i386.rpm
    在启动rpc.rstatd时,会报错“Cannot register service: RPC: Unable to receive; errno = Ction refused”

    解决方法如下:

    # /etc/init.d ./portmap start
    # /etc/init.d ./nfs start
    然后再次启动rpc.rstatd就好了。


    最后,在controller中,将UNIX resources拖放到右边窗口里面,右击鼠标选择Add Measurements,添加被监控linuxIP地址,然后选择需要监控的指标就可以了。


    三、监控UNIX
    lr
    监控UNIX UNIX先启动一rstatd服务


    以下是在IBM AIX系统中启动rstatd服务的方法:
    1
            使用telnetroot用户的身份登录入AIX系统
    2
            在命令行提示符下输入:vi /etc/inetd.conf
    3
            查找rstatd,找到

    #rstatd   sunrpc_udp     udp     wait    root    /usr/sbin/rpc.rstatd rstatd 100001 1-3
    4
    、将#去掉
    5
    :wq保存修改结果
    6
    、命令提示符下输入:refresh –s inetd 重新启动服务。
    这样使用loadrunner就可以监视AIX系统的性能情况了。

    注:HP UNIX系统上编辑完inetd.conf后,重启inetd服务需要输入inetd -c
    UNIX
    上也可以用rup命令查看rstatd程序是否被配置并激活

    rstatd程序已经运行,重启时,先查看进程ps -ef |grep inet,然后杀掉进程,再refresh –s inetd进行重启

     

  • perl+shell+实现自动化测试

    iseedeadpeople 发布于 2010-03-08 15:48:36

    目录

    第一章 项目技术背景介绍

    1.1 项目背景

    1.2 技术背景

    1.3词汇解释

    第二章 测试方案的设计

    2.1 需求分析

    第三章 测试工具的设计与实现

    3.1 测试工具的设计

    3.2 测试工具的实现

    3.2.1 Linux服务器的远程控制

    3.2.2 应用程序的启动与停止

    3.2.3 测试时间的控制

    3.2.4 本地命令的执行

    3.2.5 远程文件的拷贝

    3.2.6 测试结果写入Excel

    3.2.7 多个测试用例的执行

    第四章 测试工具的使用

    4.1 用例脚本的编写

    第五章 使用总结

    5.1 常见问题

    5.1.1 常见问题1

    第六章 尚需解决的问题

    第七章 附录

    7.1 作者介绍及联系方式

    7.2 参考资料

    7.3 源代码


    项目技术背景介绍

    项目背景

      略。

    技术背景

    测试环境为RedHat Enterprise Linux ,测试数据的采集使用Linux自带的工具toptcpdumptethereal。自动化测试工具的开发使用Linux自带的Perl,版本为v5.8.5 built for for i386-linux-thread-multi

    PerlPractical Extraction and Report Language)一般被称为“实用报表提取语言”。

    Perl 最初的设计者为Larry Wall,它于19871218发表。Perl借取了Csedawkshell scripting以及很多其他程序语言的特性。“懒惰”的Larry为了找到一个更好的解决问题的方法,从而发明了这个强大的语言。

    Perl的解释程序是开放源码的免费软件。Perl的可移植性强。如果对脚本语言感兴趣的话,你会发现,Perl,很好,很强大。

    更多关于Perl的内容可以在www.perl.org上找到。

    词汇解释 

    词汇名称

    词汇含义

    备注

       

     

    crontab

    Linux任务计划工具

     

    Expect

    以脚本形式实现交互式应用程序的语言

     

    Scp

    Linux拷贝远程文件的工具

     

    用例脚本

    按照一定的关键字、格式,将测试用例(前提条件、输入、执行步骤)写成脚本形式,供测试工具解析并执行

    使用这种方法的优点是可以扩展用例

    测试方案的设计

    需求分析

    通过分析测试用例,根据用例重要程度、执行频度、是否可以自动化,总结出以下可以使用测试工具来实现自动化测试的功能点:

    l         根据用例的前提条件,修改应用程序的相关配置

    l         启动(停止)应用程序

    l         收集应用程序的各项性能指标,如:CPU、内存、带宽、消息传输延时等

    l         控制测试时间

    l         分析各项性能指标,写入Excel,画出折线图

    l         备份系统日志及测试结果数据

     

    为使测试过程简化,并方便以后的回归测试,开发的自动化测试工具,应该具有以下功能:

    l         可以控制NN>10)台Linux服务器,可以执行命令或脚本、拷贝文件等;

    l         可以获取系统性能指标,如:CPU、内存、带宽等;

    l         可以将系统性能指标分析并写入Excel,方便画出折线图;

    l         可以扩展测试用例。

    测试工具的设计与实现

    测试工具的设计

    如图3.1-1所示,测试工具的工作流程分为3个部分:

    l         读取用例:此处的“用例”是提前按照一定的格式设计好的,就是把我们设计的测试用例再翻译成一种可以让用例解析工具“看”的懂、可以帮你自动执行的脚本,详细信息请参考4.1 测试用例的编写。

    l         执行用例:执行用例中的内容,需要之前设计好的用例是完全正确的。

    l         生成测试结果:将用例中涉及到的测试数据结果保存,并对测试结果分析、整理

    3.1-1 测试工具设计

    从上图中可以看出,用例执行是测试工具的重要部分,如何在多台Linux服务器上执行测试用例是测试工具的核心部分。经过分析,欲实现远程控制Linux服务器,并且执行特定的命令,有以下3种方案:

    l         使用Cronjob:  Linux 中,任务可以被配置在指定的时间段、指定的日期、或系统平均载量低于指定的数量时自动运行。可使用自动化的任务来执行定期备份、监控系统、运行定制脚本等等。使用Linux crontab可以配置服务器的启动,缺点是任务执行的时间需要预先设置,不灵活。

    l         ssh 命令:使用ssh脚本在服务器上执行预期的命令。如以下脚本实现了在192.168.0.1这台服务器上执行“ls”命令:

    #! /usr/bin/expect

    spawn ssh user@192.168.0.1 ls

    expect “*password:”

    send 123456\r

    expect eof

    exit

    l         C/S模式:在每个服务器上启动一个小的客户端程序,通过在Server端向客户端发送消息实现在服务器上的操作,比如:向192.168.0.1发送“ls”以执行命令。经测试,可以使用Linux自带的Perl(v5.8.0)实现,缺点是需要在多台服务器上运行客户端,自动化程度不能满足要求,另外通过perlSocket包控制多个客户端,工作量比较大,短时间内不易完成。

    第二种方案简单易与实现,最终选择第二种方案。这一部分是整个任务的难点,直接影响到后续的功能是否可以实现。

    测试工具的实现

    3.2.1 Linux服务器的远程控制

    通过学习Expect的用法,使用expect语句实现在远程机器上执行命令的功能,如:

    expect –c “spawn ssh $remote_user@$remote_ip $remote_cmd;

    expect “*password:”;

    send $remote_password\r;

    expect eof;”

    以下是实现远程控制 Linux服务器的子函数:

    3.2-1 控制远程Linux服务器

    3.2.2 应用程序的启动与停止

    用例脚本中用“start”、“stop”作为关键字来区分对应用程序的操作。

    l         应用程序的启动:在远程服务器上执行命令以启动应用程序,检查该进程是否存在,若存在,返回进程ID,并提示启动成功;若不存在,提示启动失败。

    l         应用程序的停止:根据应用程序的进程ID,使用kill的方法,停止应用程序,检查该进程是否存在,若不存在,提示停止应用程序成功;若仍存在,提示失败。

    3.2.3 测试时间的控制

    不同的测试用例,测试的时间不一致,可以使用“sleep time”来实现控制测试时间。用例脚本中用“sleep”作为关键字来控制测试时间。

    3.2-2 测试时间的控制

    3.2.4 本地命令的执行

    用例脚本中用“local”作为关键字执行本地命令。使用Perlsystem函数来调用本地命令,如执行“ls”命令,可以使用:

    3.2-3 本地命令的执行

     

    3.2.5 远程文件的拷贝

    远程文件的拷贝用Linux下的scp 命令来实现,如拷贝192.168.0.1上的/home/niwp/temp.log,可以使用如下命令:

    3.2-4 远程文件的拷贝

     

    具体实现代码,请参考附录部分。

    3.2.6 测试结果写入Excel

    可以按照测试用例的步骤编写测试脚本进行测试了,在得到测试结果后对数据进行一下处理,把log中的数据输出到Excel中,这样可以直接出图表了。这个部分使用Perl

    Spreadsheet::WriteExcel模块来完成,Spreadsheet::WriteExcel的使用可以输入:

      # perldoc Spreadsheet::WriteExcel

    下面就举个简单的例子,创建一个Excel workbook,添加多个worksheet,并写入数据:

    3.2-5 Perl新建 Excel代码

     

      执行后,可以得到名字为‘test.xls’的Excel文件,其内容如下:

    3.2-6 创建成功

    3.2.7 多个测试用例的执行

    在执行用例时,可以用测试用例的名称做为参数来使用此工具,每个用例执行完成后,都会创建与用例名称对应的文件夹,用来存放测试结果。如依次执行PA0001PA0002两个用例:

    l# ./Tester.pl PA0001 PA0002

    测试工具的使用

    用例脚本的编写

    l         启动应用程序

    start username:password@host script

    l         停止应用程序

    stop username:password@host script

     execute username:password@host “kill $(ps –ef | grep –v grep | grep xxx | awk ‘{print $2}’)“

    l         测试时间控制

    sleep time

    l         测试日志备份

    copy username:password@host log /destination

    l         测试数据处理

    local “./log2excel.pl”

        以下是测试用例PA0001的测试脚本:

     

    4.1-1 用例脚本内容


    使用总结

    常见问题

    5.1.1 常见问题1

    expect的使用时,需注意timeout的设定问题。当执行一系列命令后,expect脚本会等待结束符“eof”的出现,如果一直没有出现,直到timeout时间已到,该进程会退出。

    尚需解决的问题

    l         有密码验证登录和无密码验证登录没有考虑到,实际使用时可用两个函数来实现;

    l         测试完成后数据处理的部分要根据实际的测试数据来完成其特定功能;

    l         启动应用程序过程中,如果某一台服务器上的应用程序启动失败,会继续执行,需要根据实际情况修改,且对应用程序的配置正确性要求较高,配置错误,可能导致此次测试失败。

    原文:http://blog.csdn.net/will2ni/archive/2009/11/02/4759373.aspx#_Toc216236557
  • 【转】详解个人职业生涯规划

    paulinetina 发布于 2010-08-17 00:19:36

      个人职业生涯规划的选择和努力比没有规划的选择和努力,个人成长得更快,也成长得更好。在面临新的择业机遇,跳与不跳之中该如何规划自己的职业选择和方向呢?

      张彬,大学毕业在一家知名的大公司做助理,做到第三年,有不少公司来聘请他去,而且薪水开的很高,非常地诱人。但是,他都拒绝了。到这里,也许很多人会不理解。这么好的机会,可是过了这个村就没有那个店啦!然而,他在第六年,接受了一家公司的聘请,做了总经理!而且,做得非常好。这件事说明什么呢?工作中,会遇到很多选择机会,在跳槽时,不仅考虑当下利益,更要考虑长远发展,这个长远发展,就是职业生涯规划

      据前程无忧网统计,在跳槽中,有个人职业生涯规划的选择和努力比没有规划的选择和努力,个人成长得更快,也成长得更好。那么,作为一个有志有为青年,在面临机遇,跳与不跳之中,又该如何规划自己的职业选择和方向呢?

    个人职业生涯规划 选择比努力更重要

      张彬后来说:“第三年,我觉得还没有把那家公司的精髓学会,可以说还不是很了解,只知道老板虽然只有那么两下子!但这两下子的背后是什么,我还没有弄明白,也没有琢磨透。5年下来,我才真正体会和学习到它的精髓所在!所以,这个时候我才决定走。”

      人的一生都是在学习,不论好的,坏的;只有深入地学习,才会知道“为什么”而不是简单地知道“是什么”或“怎么样”。这也就是营销里说的“WHAT” 和“WHY”。只有知道了“why”,然后才知道如何去做,如何做好!(HOW TO DO IT !)对于年轻人来说,最可怕地就是受不住外面的诱惑,只看到短期利益,忘了自己的职业取向,在职业理想和现实状况的天平发生严重偏移时,本能地选择了后者。而殊不知,如果我们把它放到一生的职业天平来看,却发现不但不能有利于职业的发展,而且和职业取向是完全相偏的或者是相违背的。到头来,在外面诱惑和无奈了一圈后,还是回到了原来的职业起点,重新回归自己的职业认知和规划。而此时,往往又错失了很多有利于职业积累的机会。这就是为什么很多企业里,有不少出去的人又回流的现象(其实,这已不能用什么好马是否吃不吃回头草来解释了,更多的基于自己职业理想的一种深层理性判断和回归)。

      当然,选择同时是与耐得住寂寞、坚持住方向和对自己的自信联系在一起,前面,张彬就做到了这一点,他是一个成功的跳槽者。很多人,在选择了企业和老板后,在短期内不能快速实现自己的职业目标时,而与此同时,看到许多朋友和同学都开始“飞黄腾达”后,判断短期内等待和努力都不会有机会的时候,便萌生去意。殊不知,机会往往就在他离去之后就绽放了。而这种选择的本身也就是对自己以前的选择的抛弃和对自己的不自信。

      李建伟,4年前毕业于一个很普通的专科学校。自己找到了浙江萧山的一家民营企业。与他一起同往的还有浙大、杭州商学院、上海交大的。李建伟在经过了半年多的车间的“染缸染房的高温水煮”日子后(那段时间体重下降了近20斤),被提到总裁办公室任当副主任,一同提升的还有人事主管B君,其余的受不了如此的“虐待”,纷纷离去。一年半后,B君熬不住民企的用人机制和氛围,看不到自己的职业希望(依然还是人事主管),同时,看到外面的机会不断地向他招手,于是他也“水往高处流”了。然而,半年后,李建伟就坐上了总裁办主任的位置,并且还兼着人事部主任。如今的李建伟,是集团下属房地产公司的老总了,已经是 “五子登科”了。而同时进去的那些高材生们包括B君却依然还在全国各地为生存而努力地来回反复奔波着。

      我们说,选好了方向,就要坚持。选择比努力更重要。

      当然,在选择时,我们必须把握好几个原则:

      大型公司选文化,中型公司选制度,小型公司选老板。

      好行业不如好企业,好企业不如好老板,好老板不如好上司。

    个人职业生涯规划 别轻易放弃

      有这样一个朋友,将近一年前,因妈妈身体不好要做手术,到北京各大医院去打听做胸腔手术哪个医生最出色,跑了半年才找到。由此她想到应该有很多人有此困惑,尤其是外地人更不知道,而医院也特希望提高自己的知名度,强化自己的优势资源。于是,一个三十多岁的女人,没有任何的背景,也没多少钱,开始执著的追寻她的梦想,她想办一个刊物,介绍中国各地的名医名院,帮助那些和她有着同样苦恼的人。她跑遍了北京的各大医院去跟各个科室各个领导谈,企图说服他们,刚开始没人理她,她就一次次地跑,用她的热情,她的执著,晓之以情,动之以利。她又跑卫生部,又跑国家新闻出版署,通过一层又一层的关系,终于在每天一次又一次地送报告,一遍又一遍地找人的3个月后,她拿到了一个全国刊号,杂志名字叫《中国医生》。拿到刊号后,于是她又去找赞助,第一家企业是丽珠得乐,一次给她投了18万。现在她已经拿到了北京二级甲等医院40多家的惟一授权,她免费地给这些医院做宣传,然后利用这些授权再去找赞助。现在她又在石家庄的几个药厂谈赞助。她用那18万聘请了编辑、记者、排版。她的试刊号已经出来了,将在北京上海广州三地同时发行。前两天看到这位大姐很是心疼她,这几个月把她折腾的都有些变形了,一看就是长时间作息不规律造成的,但她的眼神特别地神采奕奕,干劲十足。可是几个月前,大家还嘲笑她异想天开,认为她简直是疯了。

      但是现在呢说她疯了的人呢?依然在过着当一天和尚撞一天钟的生活!而她却开始了自己新的事业。

      职业也罢,事业也罢,坚持和不放弃就是最好最大的资本。

      外面的世界很精彩,在大家都受不住外面的诱惑而纷纷放弃或改弦更张时,哪怕是一个错误的选择,只要你坚持到最后,你也就成功了。

      记得有一位前辈专家说过这样的一句话,只要你所在企业不是太差,老板不是太坏,而且你也不是很聪明,但工作还是比较尽心尽力的,只要你能够呆下去,你就成功了,你也就可以得到你想得到的。哪怕你真的一无是处。

      此话粗看,简直是贻笑大方。

      然而,细细一想,再对照现实中的朋友或同事来看,莫不如此!

      我有3个朋友,第一个很聪明也很能干,第二个很聪明但不太能干,第三个不太聪明但工作很卖力。3年前,第一个进入一家很有名的公司,第二个进了一家很有发展前景的公司,第三个进了一家大家都不看好的小型公司。然而,3年后,第一个已经换了3个单位,目前据说,又要跳了,好像还没有找到自己的职业发展方向。做到的最高职位也只是项目经理。第二个还是呆在那家企业,不过已经做到了公司部门主管,在大家纷纷外求高薪内转高职时他无地可去只好呆在原部门。然而,部门总监感觉到如果再不提拔留下来的人,可能都要跑掉和内部转岗了。于是,一下子破格提升了好几个职位,矮子中拔高个子。有幸第二个朋友比较聪明,于是他也成了受益者。而第三个朋友知道自己比较笨,于是拼命地工作,更多地付出,与公司共同成长。现在,他们的公司经过3年的努力已经由行业的第六位做到行业的第二位,公司总部也已搬到了上海,他也做到了副总的位置。

      这就像掘井人的故事一样。掘井人到了一个地方,就拼命地挖井,可是挖了很长一段时间后还是见不到水,于是,就赶紧又换一个地方挖。殊不知,只要他再坚持挖几下,就可以见到水了,但是他没有坚持,却被后来的坚持者稍稍挖一两下就见到了水。水就这样被挖到了!

      现实生活中,往往比较有能力的人对自己也看得过重,于是,在短期得不到自己想要的时候,就想到另外的地方去实现自己的目标。而到了另外一个地方,由于有了前面时间的浪费和能力的铺垫,往往对企业的期望就更高了,就想得到更多,而企业在给与取的过程中,是有其本身内在的习惯和文化的。于是,能力强者就在这不断的选择中放弃了自己本应得到的东西,而这种循环和流动带来的就是企业开始认识到自身用人的不足,开始反馈和乐施留下来的员工。于是,坚持留下来者,哪怕他本身也就没有什么大本事,就都成了利益受益者。

      现实职场中,我们又有多少这样的掘井人呢?真正受益者却又是谁呢?我们每个是否也在演绎着掘井人的角色呢?

    个人职业生涯规划  你有职业规划吗?

      职业生涯规划就是准确评价个人特点和强项,评估个人目标和现状的差距,发现新的职业机遇,突破生活的格线,重新认识自身的价值并使其增值,准确定位职业方向,要以既有的成就为基础,将个人、事业与家庭联系起来,确立人生的方向提供奋斗的策略,增强职业竞争力。

      那么,作为单独的个体,我们又该如何规划自己的职业生涯,选择自己的职业方向呢?

    一、“盘点”自己——决定:留下来还是离开?

      请看上图(该图出自于麻省理工Mr. E.H.Schein教授)。在这张图中,不同的椭圆代表了在一个企业中不同的层级,越向上当然是职位级别越高;在同一个椭圆上代表职位级别相同,但工作职能不同,如HR主管、生产主管、销售主管或财务主管等。根据图中直线和箭头的方向,我们可以清楚地看到,每个人有3种可能的发展趋势和职业方向:

      1.向上发展,可以沿着椭圆边上的直线向上。比如在销售部门,荣升为销售主管或销售经理或销售总监等。

      2.横向发展,如果没有提升的机会,也可以在同一椭圆内(同一级别)向本部门的其他职位或别的部门发展,扩大工作领域,增加工作经验,提升职业宽度和职业综合竞争力。

      3.在椭圆中心向上发展,这是一种微妙的发展,必须充分理解企业*,具有融圆的人际关系和人脉关系。比如说,有两个人同样在职位上属于部门主管,是同一个级别,但他们可能跟椭圆中心(最高决策层或管理层)的距离是有远近的,即有人能更多地得到领导的器重和使用,除了具有一定的管理地位和话语权外,还能得到一些专门的特权或特别的培养或融入最高决策层或管理层的工作之外的领域等等,因此这种机会是更难得的,一旦获得这样的机会,职业的成长线就是坐直升飞机提升。

      盘点自己目前在公司的现状,是在图上的哪个位置上,有哪些可能转岗、晋升或重用的机会呢?是否值得等待、争取或创造呢?

      所以,通过评估现状和盘点自己,就可以顺理成章地做出留下来还是离开的决定。如果选择留下来,则需要:根据自己的兴趣和职业发展设定发展目标——结合企业的实际和可能做出职业计划——在奉献给企业的同时实施行动——在企业调整目标和策略的过程中评估和修正自己的计划——根据调整好的计划并结合目标再实施行动。

      如果选择离开,那又如何重新定位呢?可以这样考虑和自我分析:

      首先自我因素分析。

      1.“我的喜好是什么?”这可能使你寻求“舒适”(符合自己喜好的事情)的而不是有效的行动。你是否仅限于自己所偏好的行为?你是否扩大了你的爱好内存? 

      2.“我的观点和信仰是什么?”这或许扭曲你对于世界和自己的认识。你是以之为行为根据吗?或者你在坚持不合适的信念?

      3.“我的需要和动机是什么?”这可能使你去从事非建设性的管理活动。你能否一直成功地驾驭它们?

      4、“我的感情和情绪怎么样?”你是压抑它们呢还是驾驭它们?抑或是用它们来创造活力或动 力?

      5、“我的个性怎么样?”你是如何扬升避短或取长补短的?

      其次外界因素分析。

      1.国家的政策支持?分析要素:方向、时间、区域等。

      2.行业的发展状况?分析要素:趋势、竞争程度、对手及上下游价值链。

      3.企业的发展状况?分析要素:老板、高阶管理者、企业文化和制度、产品和市场。

      最后找到内外因素的结合点,根据自己的成就动机、心理素质条件、行业知识和专业知识储备、家庭和资金的条件及人脉关系的积累等诸多因素综合考虑,便可得出自己可发展的职业选择:是继续就业、转型或者创业还是学习,等等。

    二、“规划”自己——决定:从哪里来VS到哪里去?

      在规划自己的职业生涯时,最重要的是要找准和设定好自己职业生活线。那么,职业生活线又该如何设定和规划呢?

      规划职业生活线的目的是帮助你从过去的职业中展望未来,以便确定你在职场中的前进方向。

      首先,划一条你到目前为止的职业生活线。为此,先在你的人生轨迹中找到一个适合的人生起跑点为职业生活线的起点(参考要素是对你现在产生了影响或还将继续产生影响的事情。比如高考、第一份工作等),然后划一条你的人生职业生活线,直到你今天为止在职业上的现状为职业生活线的终点。

      在线上标明最高点和最低点,代表你的最高潮和最低谷。

      你可以划两条线:一条代表你的职业,另一条代表你的个人生活。

      分析你所划的线:

      1.你能指出你所曾经历的一些特别重要的经历和决定吗?

      2.你过去取得了哪些重大的成功?它们是如何实现的?

      3.你曾经从哪里获得满足和成就感?其源泉是什么?

      4.你过去曾经有过巨大的失望或挫折吗?它们是怎样出现的?你又是如何解决的?解决得怎么样?

      5.长期以来,什么是你主要的驱动力?

      6.过去曾经有人对你有特别的影响吗?他是如何影响你的?

      7.总的来说,你如何评价你的工作?你已经得到了自己想要得到的东西吗?如果没有,你能说明为什么吗(包括外因和内因)?

      下一步要分析的是你线上的“当前点”:

      1.你现在身在何处?

      2.你对现状满意吗?

      3.你如何评价自己现在工作的完成情况?好还是不好?其他人同意你的结论吗?

      4.你对当前自己能力发挥和运用的方式感觉如何?

      5.你如何评价自己的工作?你真正喜欢的是什么?

      6.有什么事是你害怕的,或者是感到特别不安的?是有待开发的领域吗?

      7.你认为自己和你的单位能从你当前的工作中获得什么?

      当你回答完这些问题后,把你的职业线尽可能理性地延伸到未来,比如5年以后,如何可能地话。

    一定要符合实际!但同时也要避免过分地限制和拘泥你的想像力。这样才可以让你决定自己真正想要什么,而不是关于你当前工作的不舒服之处,也不是关于更换工作的困难。

      接下来,朝前考虑这一未来的点,分析它对你而言意味着什么:

      你想为自己得到什么?

      1.在这一段时间里你想做出什么贡献?

      2.你想到什么地方?

      3.什么时候?

      4.为此你需要开发何种能力和技术?

      5.你将需要做什么?或要求什么?

      6.谁能帮助你?

      7.“成功”对你来说,意味着什么?

      再下一步,决定你是想要切实地朝此方向努力呢,还是仅仅把它作为一个梦想或幻想?如果是后者,那么考虑一下你为什么不想去努力实现希望中的未来。

      1.是什么阻止了你?

      2.是你自己阻止自己吗?如果是,那为什么?

      最后,请考虑,这个长期目标与你现在将要进行的选择与努力之间有什么关系?

      通过职业生活线的设定和规划,你就可以明确地知道自己目前在什么位置上?要到达什么位置?起点和终点之间有多少距离?你该如何到达?只有这样,你所有的行动才是有目标性和动力性!你所有努力也才不会因为盲目地瞎忙而茫然了。你的职业实现也就是时间问题了。

  • RFT测试对象检查器与jdk版本的兼容性问题

    dreamever 发布于 2008-07-09 09:30:58

    一、问题 我所使用的RFT是v7.0.1.2版本,一切正常。但是当我把JDK从1.4.2更新成1.6以后,测试对象检查器就出现了问题。具体表现是,当对象检 查器悬浮在IE界面上时,无论用鼠标点击那里,都无法识别出IE的任何属性。而对于RFT自带的演示程序,对象检查器可以正确的识别。
     二、分析 对比问题出现前后的工作环境,我将问题定位在了JDK上。IE使用默认的java插件,其版本与机器上所安装的JDK版本一致。可能RFT的对象检查器在 识别IE时,与IE的JAVA插件有依赖关系。RFT中的JDK是1.5版本,而我的JDK是1.6,这样有可能出现不兼容的情况(仅为个人推测)。恰巧 这时部门里一个漂亮的女同事也将JDK升级为1.6,在她的机器上,也出现了测试对象检查器不能识别IE对象的问题。
     三、解决 问题定位后就开始着手解决,首先我修改环境变量,将jdk1.6全部替换成1.4.2,重启机器,问题依旧;
     在IE的(工具——选项——程序——管理加载项)中,禁用JDK1.6插件,重启IE,问题依旧;
     同样在IE的(工具——选项——程序——管理加载项)中,点击JDK1.4.2,点击更新activeX插件,更新失败,放弃;
     在控制面板中,卸载jdk16和1.4.2,清除系统变量中所有关于JAVA的配置,然后重新安装JDK1.4.2并配置JAVA环境变量,问题依旧;
     在我的RFT中我曾经装过VSS插件,于是将VSS插件禁用,重启RFT,问题依旧,再重启机器,问题依旧;
     实在无奈,抱着机箱大喊:”我爱你“,问题依旧。 重装RFT,并升级为7.0.1.2,问题解决
    四、花絮
    今天早上,漂亮的女同事给我发消息,说这个问题不用重装也可以解决,方法是在RFT的“窗口—首选项”中,点击“JAVA—已安装的JRE”,将JDK1.6 添加进来;然后在“ECLPSE配置—启用环境进行测试“中,点击JAVA页签,将JDK1.6添加进来,最后将原来缺省的禁用。然后重启RFT就OK了, 前后不用五分钟的时间。
    想想一开始的时候我那么胡乱折腾,真是好笑。到底还是对RFT的相关功能不熟悉。
  • 一步步教你安装Quality Center 10

    Tesherlock 发布于 2010-07-22 13:03:49Top 3 Digest 3

    系统配置:
    服务器:Windows Server 2003 SP2
    数据库:Microsoft SQL Server 2005 SP2

    准备工作:

    安装QC前保证数据库已经安装成功!然后下载QC10.0客户端和License。 Quality Center 10.0下载地址: http://h30302.www3.hp.com/prdownloads/T7333-15006_1.zip?ordernumber=380460920&itemid=1&downloadid=33646252&merchantId=HP_DOWNLOAD_CENTER&dlm=ON (Quality Center 10.0的下载地址,复制到迅雷里就可下载)

    Quality Center 10.0 License:
    QC10.0_license.rar(473 B )

    开始安装:

    解压Quality Center 10.0安装文件,点击setup.exe开始安装Quality Center。

    这里输入licence,

    弹出集群配置对话框,如果是第一次安装的话,就选择第一个节点/独立。

    点击下一步。 要求选择应用服务器类型,在默认的情况下,是JBoss应用服务器的(Jboss服务器在QC中都是已经集成了的,不需要单独安装和配置的),也可以选择其他应该服务器,比如IIS,WebLogic服务器等;建议选择Jboss作为应用服务器,本例安装就是选择Jboss应用服务器。Jboss服务器默认占有的端口是8080,如果需要更改访问端口,点击【显示Jboss高级选项】修改端口即可,当然也可以在安装好后,修改相应的配置文件来修改访问端口。
     

    JBoss服务中输入用户名和域名,用户名就是windows系统管理员administrator,也可以不用填,没有任何影响;

    Web服务器也选择用Jboss,然后点击【下一步】即可。

    选择安装的附带项目。

    选择邮件服务器,如果系统有邮件服务器,可以选择邮件服务器,本次安装不选择邮件服务器,这并不会影响使用。
     

    选择SQL Server数据库类型。


    开始定义Quality Center 站点管理员的用户名和密码,输入用户名和密码即可;站点管理员就是一个拥有超级权限的用户。

    列出本次安装配置的相关信息。 

    开始进行安装,等待安装完成即可。

    安装完成后,由于使用的是Jboss服务器,需要首先启动Jboss服务器才能正常使用QC。

    至此安装完毕,安装过程中如果出现问题,请参考另一篇文章:QC10.0安装问题总结

853/5<12345>