前段时间记录的笔记,绝对不是懒才拖到现在的!
JavaEE基础 JSP:全名为 java server page ,其根本是一个简化的 Servlet 设计
Servlet:Servlet 是一种服务器端的 Java 应用程序,可以生成动态的 Web 页面。
JavaEE: JavaEE 是 J2EE 新的名称。改名目的是让大家清楚 J2EE 只是 Java 企业应用。
Web请求简要流程
配置信息一般放在WEB-INF 文件夹
例如,数据库连接配置:
大多数的 Spring 框架配置在 applicationContext.xml 中
Hibernate 框架在 hibernate.cfg.xml 中
服务器的数据源配置文件
一般情况下 Java 的数据库配置都在 WEBROOT 下的 WEB-INF 目录下的多数情况在
*.xml、*.properties、*.conf
当然也有直接写在源代码中的情况
APACHE RESIN 做负载均衡,Resin 用来做 JAVAWEB 的支持,APACHE 用于处理
静态和 PHP 请求,RESIN 的速度飞快,RESIN 和 apache 的配合应该是比较完美的吧。
域名解析:
apache 的 httpd.conf:
需要修改: Include conf/extra/httpd-vhosts.conf(一定要把前面的#除掉,否则配置不起作
用)
普通的域名绑定:
直接添加到 httpd.conf
1 2 3 4 5 6 7 <VirtualHost *:80> ServerAdmin admin@noel.cn DocumentRoot $wwwpath ServerName noel.com ErrorLog $path/error_log CustomLog $path/log common </VirtualHost>
配置好 APACHE 对 Resin 的支持后即可
第一章多为配置信息,看的不尽详细,先挖个坑,有空自己搭建环境。
XSS 漏洞原理及危害不予考虑,这里仅探究代码
创建一个 Servlet 内容如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 FirstServlet package XSS;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.PrintWriter;import java.util.Enumeration;public class FirstServlet extends HttpServlet { @Override protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html" ); PrintWriter out = resp.getWriter(); Enumeration e = req.getHeaderNames(); while (e.hasMoreElements()){ String name = (String) e.nextElement(); String value = req.getHeader(name); out.println(name + "=" + value + "<br/>" ); } out.flush(); out.close(); } }
在 Web.xml 中添加该 Servlet
1 2 3 4 5 6 7 8 9 <servlet> <servlet-name>FirstXSS</servlet-name> <servlet-class >XSS .FirstServlet </servlet -class > </servlet > <servlet -mapping > <servlet -name >FirstXSS </servlet -name > <url -pattern >/First </url -pattern > </servlet -mapping >
访问http://localhost/webapp/First 即可看到打印出来的请求头信息,只需要抓包修改任意值构造 XSS 即可
session 操作
1 2 3 4 5 设置: session.setAttribute("name" ,name); session.setAttribute("ip" ,request.getRemoteAddr()); 获取: session.getAttribute("name" );
SQL注入 jdbc SQL 注入(使用 Mysql 数据库时要先将 mysql 的 Jar 包导入项目的 lib 中)
新建一个 Java文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 SQLTest package SQL;import java.sql.*;public class SQLTest { private static String url = "jdbc:mysql://localhost:3306/hackers" ; private static String username = "root" ; private static String password = "root" ; private static Connection conn = null ; public void List (String name) throws ClassNotFoundException, SQLException { Class.forName("com.mysql.jdbc.Driver" ); conn = DriverManager.getConnection(url,username,password); String sql = "select * from users where user_name='" + name + "'" ; PreparedStatement ps = conn.prepareStatement(sql); ResultSet rs = ps.executeQuery(); System.out.println("SQL: " + sql); rs.first(); System.out.println("ID: " + rs.getString("id" )); System.out.println("Name: " + rs.getString("user_name" )); rs.close(); ps.close(); } public static void main (String[] args) throws SQLException, ClassNotFoundException { SQLTest sql = new SQLTest(); sql.List("Test" ); } }
虽然是预编译的语句,但是预编译前拼接了字符串而不是占位的方式,所以还是有SQL注入存在
修改最后一句为
1 sql.List("' union select user(),2,3,'4" );
执行
修改一下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package SQL;import java.sql.*;public class SQLTest { private static String url = "jdbc:mysql://localhost:3306/hackers" ; private static String username = "root" ; private static String password = "root" ; private static Connection conn = null ; public void List (String name) throws ClassNotFoundException, SQLException { Class.forName("com.mysql.jdbc.Driver" ); conn = DriverManager.getConnection(url,username,password); String sql = "select * from users where user_name= ? " ; PreparedStatement ps = conn.prepareStatement(sql); ps.setObject(1 ,name); ResultSet rs = ps.executeQuery(); System.out.println("SQL: " + sql); rs.first(); System.out.println("ID: " + rs.getString("id" )); System.out.println("Name: " + rs.getString("user_name" )); rs.close(); ps.close(); } public static void main (String[] args) throws SQLException, ClassNotFoundException { SQLTest sql = new SQLTest(); sql.List("' union select user(),2,3,'4" ); } }
这个时候就会因为没有查询到结果报错,也就是注入不存在了
可以 debug 跟踪一下 setObject
发现在 PreparedStatement.class 的 setString 方法下对单引号进行了处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 for (int i = 0 ; i < stringLength; ++i) { char c = x.charAt(i); switch (c) { case '\u0000' : buf.append('\\' ); buf.append('0' ); break ; case '\n' : buf.append('\\' ); buf.append('n' ); break ; case '\r' : buf.append('\\' ); buf.append('r' ); break ; case '\u001a' : buf.append('\\' ); buf.append('Z' ); break ; case '"' : if (this .usingAnsiMode) { buf.append('\\' ); } buf.append('"' ); break ; case '\'' : buf.append('\\' ); buf.append('\'' ); break ; case '\\' : buf.append('\\' ); buf.append('\\' ); break ;
x 是我们传入的,而经过处理后就变为了 parameterAsString
最后执行的语句则是
如此一来自然不存在注入
Web 应用
新建一个数据库连接类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 SQLDB package SQL;import java.sql.Connection;import java.sql.DriverManager;public class SQLDB { private static String url = "jdbc:mysql://localhost:3306/hackers" ; private static String username = "root" ; private static String password = "root" ; public static Connection getMysql () { try { Class.forName("com.mysql.jdbc.Driver" ); return (Connection) DriverManager.getConnection(url,username,password); }catch (Exception e){ e.printStackTrace(); return null ; } }
新建一个 Servlet
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 SQLServlet package SQL;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.PrintWriter;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;public class SQLServlet extends HttpServlet { private String sql; private String name; private Connection conn=null ; private PreparedStatement ste = null ; @Override protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter out = resp.getWriter(); try { name = req.getParameter("name" ); }catch (Exception e){ name = "Noel" ; } conn = SQLDB.getMysql(); sql = "select * from users where user_name='" + name + "'" ; try { ste = conn.prepareStatement(sql); ResultSet rs = ste.executeQuery(); rs.first(); out.println("ID: " + rs.getObject("id" ).toString()); out.println("Name: " + rs.getObject("user_name" ).toString()); out.println("Acount: " + rs.getObject("acount" ).toString()); } catch (SQLException e) { e.printStackTrace(); out.println("Something error~~" ); } } }
在 Web.xml 中增加如下内容
1 2 3 4 5 6 7 8 9 <servlet> <servlet-name>FirstSQL</servlet-name> <servlet-class >SQL .SQLServlet </servlet -class > </servlet > <servlet -mapping > <servlet -name >FirstSQL </servlet -name > <url -pattern >/FirstSQL </url -pattern > </servlet -mapping >
传递参数 ?name= 即可
Oracle 数据库是个坑,有空开挖。
MVC MVC 是三个单词的缩写,分别为: 模型 (Model),视图 (View)和控制 (Controller)。 MVC 模式的目的就是实现 Web 系统的职能分工。
Model 层 实现系统中的业务逻辑 ,通常可以用 JavaBean 或 EJB 来实现。
View 层 用于与用户的交互 ,通常用 JSP 来实现
Controller 层 是 Model 与 View 之间沟通的桥梁 ,它可以分派用户的请求并选择恰当的
视图用于显示,同时它也可以解释用户的输入并将它们映射为模型层可执行的操作。
Sturts2 官网下载最新文件,或者 idea 创建 Struts2 项目时下载 lib 文件,将主要的 jar 包放在 lib 文件夹下
PS:MySQL 连接文件为上一部分 SQL 中添加
创建 HelloWorldAction.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 HelloWorldAction.java package Struts2;import com.sun.net.httpserver.Authenticator;public class HelloWorldAction { private String name; public String execute () { return "success" ; } public String getName () { return name; } public void setName (String name) { this .name = name; } }
这是一个非常简单的具有“name”属性的类。对于“name”属性,我们用标准的getter和setter方法,以及一个返回“success”字符串的执行方法。Struts2 框架将创建一个“HelloWorldAction”类的对象,并调用execute方法来响应用户的动作。业务逻辑放进 execute 方法里,最后会返回字符串常量。name 可通过 get 或者 post 方法获取
web 目录下新建 index.jsp , HelloWorld.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 index.jsp <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" %> <%@ taglib prefix="s" uri="/struts-tags" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" ><html> <head> <title>Hello World</title> </head> <body> <h1>Hello World From Struts2</h1> <form action="hello" > <label for="name">Please enter your name</label><br/> <input type="text" name="name" id="name" /> <input type="submit" value="Say Hello" /> </form> </body> </html>
1 2 3 4 5 6 7 8 9 10 11 HelloWorld.jsp <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="s" uri="/struts-tags" %> <html> <head> <title>Hellow World</title> </head> <body> Hello World,<s:property value="name" /> </body> </html>
Taglib指令告知Servlet容器这个页面将使用Struts2 标签,并且这些标签会被s放在前面。s:property 标签显示Action类“name”属性的值,这个值是使用 HelloWorldAction 类的 getName() 方法返回的。
src 目录下新建 sturts.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd" > <struts > <constant name ="struts.devMode" value ="true" /> <package name ="helloWorld" extends ="struts-default" > <action name ="hello" class ="Struts2.HelloWorldAction" method ="execute" > <result name ="success" > /HelloWorld.jsp</result > </action > </package > </struts >
package 定义数据包,当有多个 Action 时数据包非常有用,name 为数据包命名
action name 设置为 hello 对应路由 /hello.action, class 指定了确切的动作 HelloWorldAction ,如果 execute 方法返回的值是 success 的话,将进入 HelloWorld.jsp
为 Web.xml 配置filter
1 2 3 4 5 6 7 8 <filter > <filter-name > struts2</filter-name > <filter-class > org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class > </filter > <filter-mapping > <filter-name > struts2</filter-name > <url-pattern > /*</url-pattern > </filter-mapping >
运行程序
STRUTS2 框架内部流程 :
\1. 客户端发送请求的 tomcat 服务器。服务器接受,将 HttpServletRequest 传进来。
\2. 请求经过一系列过滤器(如:ActionContextCleanUp、SimeMesh 等)
\3. FilterDispatcher 被调用。FilterDispatcher 调用 ActionMapper 来决定这个请求是否要调用某
个 Action
\4. ActionMapper 决定调用某个 ActionFilterDispatcher 把请求交给 ActionProxy
\5. ActionProxy 通过 Configuration Manager 查看 struts.xml,从而找到相应的 Action 类
\6. ActionProxy 创建一个 ActionInvocation 对象
\7. ActionInvocation 对象回调 Action 的 execute 方法
\8. Action 执行完毕后,ActionInvocation 根据返回的字符串,找到对应的 result。然后将 Result
内容通过 HttpServletResponse 返回给服务器。
Struts2 请求处理流程分析:
服务器启动时会自动去加载当前项目的web.xml
在加载 web.xml 配置的时候会去自动初始化 Struts2 的 Filter,然后把所有的请求先交 Struts 的 StrutsPrepareAndExecuteFilter.java 类去做过滤处理.
而这个类只是一个普通的 Filter 方法通过调用 Struts 的各个配置去初始化。
初始化完成后一旦有 action 请求都会经过 StrutsPrepareAndExecuteFilter 的 doFilter 过滤.
doFilter 中的 ActionMapping 去映射对应的 Action。
ExecuteOperations
ST2-016:
暂时还是个坑……有空分析
Spring MVC 使用 idea 新建 Spring MVC 项目
web.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <web-app id ="WebApp_ID" version ="2.4" xmlns ="http://java.sun.com/xml/ns/j2ee" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" > <servlet > <servlet-name > HelloWeb</servlet-name > <servlet-class > org.springframework.web.servlet.DispatcherServlet </servlet-class > <load-on-startup > 1</load-on-startup > </servlet > <servlet-mapping > <servlet-name > HelloWeb</servlet-name > <url-pattern > /</url-pattern > </servlet-mapping > </web-app >
HelloWorld-servelt.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:context ="http://www.springframework.org/schema/context" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation =" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd" > <context:component-scan base-package ="controller" /> <bean class ="org.springframework.web.servlet.view.InternalResourceViewResolver" > <property name ="prefix" value ="/WEB-INF/jsp/" /> <property name ="suffix" value =".jsp" /> </bean > </beans >
HelloController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package controller;import org.springframework.stereotype.Controller;import org.springframework.ui.ModelMap;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.servlet.ModelAndView;@Controller @RequestMapping ("/hello" )public class HelloController { @RequestMapping (method = RequestMethod.GET) public String printHello (ModelMap model) { model.addAttribute("message" ,"Hello Spring MVC Framework!" ); return "index" ; } }
方法上方有一个 @RequestMapping, 是用于匹配请求的路径, 返回的 index 结合 HelloWorld-servelt.xml 表示加载 /WEB-INF/jsp/ 下的 index.jsp 文件
index.jsp
1 2 3 4 5 6 7 8 9 <%@ page contentType="text/html; charset=UTF-8" %> <html> <head> <title>Hello World</title> </head> <body> <h2>${message}</h2> </body> </html>
message 为 Hello 中设置的 message
Server 各种服务器相关漏洞,后续慢慢填充