Java安全基础 Web架构
该学下java安全了
Java安全基础 Web架构
Java Web 一般由web 服务端和web 客户端两部分组成
JavaWeb 服务端架构大致先后以下面几个阶段演变的:
- Servlet
- JSP
- Struts –>SSH(Struts+Spring+Hibemate)
- Spring MVC –>SSM(Spring+Spring MVC+Mybatis)
- SpringBoot
- SpringCloud
- 等。。。
Java EE
Java EE指的是Java平台企业版(Java Platform Enterprise Edition)
之前称为Java 2 Platform, Enterprise Edition(J2EE),2017 年的 9 月Oracle将Java EE 捐赠给 Eclipse 基金会,由于Oracle持有Java商标原因,Eclipse基金于2018年3月将Java EE更名为Jakarta EE。
Java EE 是在 Java SE(Standard Edition) 的基础上建立的,并增加了许多额外的特性和技术来方便构建高可用的企业级应用。
平台版本 | 发布日期 | 规范 | Java SE支持 | 重要变化 |
---|---|---|---|---|
Jakarta EE 10 | 2022-09-13 | 10 | Java SE 17, Java SE 11 | 移除Servlet、Faces、CDI和EJB (Entity Beans和Embeddable Container)中的过时项,CDI-Build Time。 |
Jakarta EE 9.1 | 2021-05-25 | 9.1 | Java SE 11, Java SE 8 | JDK 11支持 |
Jakarta EE 9 | 2020-12-08 | 9 | Java SE 8 | API命名空间从javax移动到jakarta |
Jakarta EE 8 | 2019-09-10 | 8 | Java SE 8 | 与Java EE 8完全兼容 |
Java EE 8 | 2017-08-31 | JSR 366 | Java SE 8 | 基于CDI的安全性和HTTP/2 |
Java EE 7 | 2013-05-28 | JSR 342 | Java SE 7 | WebSocket、JSON和HTML5支持 |
Java EE 6 | 2009-12-10 | JSR 316 | Java SE 6 | CDI托管Bean和REST |
Java EE 5 | 2006-05-11 | JSR 244 | Java SE 5 | Java注解 |
J2EE 1.4 | 2003-11-11 | JSR 151 | J2SE 1.4 | WS-I可互操作的Web服务 |
J2EE 1.3 | 2001-09-24 | JSR 58 | J2SE 1.3 | Java连接器架构 |
J2EE 1.2 | 1999-12-17 | 1.2 | J2SE 1.2 | 最初的规范发布 |
Servlet
Servlet 这个名字是 Server Applet 的缩写,即服务端小程序,通常被用来处理一些较为复杂的服务器端的业务逻辑。
Servlet是Java EE的核心,可以说是 Java Web 开发中基础的基础,也是所有的MVC框架的实现的根本!
Servlet 运行流程
servlet运行在servlet容器中,每次运行web服务都会起一个servlet容器,容器内包含了很多servlet来被调用
也就是说,我们在浏览器的web页面访问特定的路由,来触发指定servlet,容器内的指定servlet再根据我们写好的处理逻辑执行我们规定好的流程
比如:写一个servlet用于输出指定内容111,当访问/flag
是执行该servlet,当我们访问/flag时,便会回显111
Servlet 生命周期
Servlet 的生命周期分为:
- init()
- service()
- do..() 例:doGet()、doPost()
- destroy()
由字面意思就可以大致理解这些生命周期的意思
servlet启动后会先进行初始化init(),然后就一直存在于容器中,等待被调用service(),
当有servlet被调用,service()就会判断请求的类型,执行对应的do..()操作,例如:doGet()、doPost()
当容器关闭,即web程序退出时,便会执行destroy(),结束整个servlet的生命
Servlet的定义
在正式开始使用Servlet还需要了解一下它的定义
定义一个 Servlet 很简单,只需要继承javax.servlet.http.HttpServlet
类并重写doXXX
(如doGet、doPost
)方法或者service
方法就可以了
需要注意的是重写HttpServlet类的service方法可以获取到上述七种Http请求方法的请求。
javax.servlet.http.HttpServlet
不仅实现了servlet
的生命周期,并通过封装service
方法抽象出了doGet/doPost/doDelete/doHead/doPut/doOptions/doTrace
方法用于处理来自客户端的不一样的请求方式,我们的Servlet只需要重写其中的请求方法或者重写service
方法即可实现servlet
请求处理。
1 |
|
先把写好的demo代码放着
基于Web.xml配置
Servlet3.0
之前的版本都需要在web.xml
中配置servlet标签
servlet标签是由servlet
和servlet-mapping
标签组成的,两者之间通过在servlet
和servlet-mapping
标签中同样的servlet-name
名称来实现关联的。
而在 Servlet 3.0 之后( Tomcat7+)可以使用注解方式配置 Servlet 了
在任意的Java类添加javax.servlet.annotation.WebServlet
注解即可。
1 |
|
这简化了Servlet的配置方式,但同时Servlet的定义就不仅仅存在于web.xml,还需要去包含了@WebServlet
注解的类
而要想通过web.xml来定义servlet,只要要在web.xml中添加如下内容(以刚才写好的demo为例)
1 |
|
使用Servlet
配置环境
创建一个Maven archetype为webapp的项目:
然后在新建的项目里的pom.xml中引入servlet依赖
1 |
|
安装Tomcat,从官网下载编译好的Tomcat(Core),这里下的10后面报错了,版本太高,换8就好了
配置好本地Tomcat
选择 war exploded 方式
war exploded 方式 :常在开发的时候使用这种方式,它可以支持热部署,但需要设置。
之后就是在项目中写入我们之前写好的demo
1 |
|
别忘了重载一下pom.xml的依赖,不然可能会报错
完善webapp项目结构,参考:https://blog.csdn.net/little_doggy_/article/details/130478571
在web.xml添加
1 |
|
都准备好后,启动,然后访问/HelloServlet
就可以看到了
同样的,由于我们的servlet版本是3.1,可以采用注解方式代替web.xml的配置
Servlet 3.0 特性
新增动态注册Servlet、Filter 和Listener的API(addServlet、addFilter、addListener)。
新增@WebServlet、@WebFilter、@WebInitParam、@WebListener、@MultipartConfig注解。
文件上传支持,request.getParts()。
非阻塞 IO,添加异步 IO
可插拔性(web-fragment.xml、ServletContainerInitializer)
1 |
|
web.xml注释掉原有的注释
1 |
|
遇到啥报错,网上搜一般都可以解决,这是刚接触servlet,对于它的结构算是有初步的了解,明天打算多写点代码练练手
Filter&Listener
Filter
也是Servlet中常用的特性,是使用javax.servlet.Filter 接口进行实现的,可以用于为所有 Servlet 添加全局性的鉴权和过滤
可以用于过滤特殊的字符编码,防护一些sql注入等常见的漏洞
1 |
|
写一个简单的Filter,当路径是包含”/HelloFilter”时输出Hello Filter,不包含时则跳转到/HelloServlet
访问/a
访问/HelloFilter
JSP
要想使用 Servlet 在生成网页中动态的内容(类似php等其他语言),但由于所有文本和标签都是硬编码,如果想要做出修改,每次就需要重新对源码进行再次的编译部署,麻烦了些,无法像php那样修改.php文件就可以即插即用。
而 JSP (Java Server Page)可以有效解决了 Servlet 的这些问题
JSP 基于Java 语言,类似于php,是一种动态网页技术。通过使用 JSP 标签在HTML 网页中插入 Java 代码。标签通常以<% 开头,以%>结束。
1 |
|
JSP、Servlet之间的关系
JSP 本质是简化版的Servlet,JSP 在编译后就变成了Servlet。JVM 只能识别Java的类,是无法识别JSP 代码的。所以WEB 服务器会将JSP 编译成JVM 能识别的Java 类。
JSP 跟Servlet 区别在于,JSP 常用于动态页面显示,Servlet 常用于逻辑控制。在代码中常使用 JSP 做前端动态页面,在接收到用户输入后交给对应的Servlet 进行处理。当然JSP 也可以当做后端代码进行逻辑控制。
JSP 生命周期: 编译阶段 -> 初始化阶段 -> 执行阶段 -> 销毁阶段
此处多了一个编译阶段,是将JSP 编译成Servlet 的阶段。而这个阶段也是有三个步骤的: 解析JSP 文件 -> 将JSP 文件转为servlet -> 编译servlet 。
在编译阶段,JSP文件会被编译成java类文件,如index.jsp在Tomcat中Jasper编译后会生成index_jsp.java
和index_jsp.class
两个文件。
- 生成的类名与 jsp 文件名相同,不合法的字符会转换为
_
,比如index.jsp
会生成index_jsp
,1.jsp
会生成_1_jsp
; - 生成的 Java 类(如:index_jsp.java)继承自抽象类 HttpJspBase(一个实现了HttpJspPage接口并继承了HttpServlet的标准的Servlet)
- 生成类的代码中的
_jspInit
、_jspDestory
对应 Servlet 中的生命周期函数;_jspService
中处理客户端的请求,类似于Servlet中的service方法,其实就是HttpJspBase
的service
方法调用
基本语法
一般JSP文件后缀名为.jsp
jsp引擎则可能会解析jspx
/ jspf
/ jspa
/ jsw
/ jsv
/ jtml
等后缀的文件
<% code %>
scriptlet 可以用来包裹和执行 Java 代码,也可以用<jsp:scriptlet>
标签来进行包含;
1 |
|
<%! declaration; [ declaration; ]+ ... %>
用于变量声明,同<jsp:declaration>
;<%= expr %>
用来包括和执行表达式,表达式的结果作为 HTML 的内容,同<jsp:expression>
;<%-- comment --%>
为 JSP 注释,注释中的内容会被 JSP 引擎忽略;<%@ directive attribute="value" %>
指令,影响对应 Servlet 的类结构<jsp:action_name attribute="value" />
使用 XML 控制 Servlet 引擎的的行为,称为 action;…
JSP 三大指令
<%@ directive attribute="value" %>
指令,影响对应 Servlet 的类结构
<%@ page ... %>
定义网页依赖属性,比如脚本语言、error页面、缓存需求等等<%@ include ... %>
包含其他文件(静态包含)<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
引入标签库的定义
JSP 九大对象
从本质上说 JSP 就是一个Servlet,JSP 引擎在调用 JSP 对应的 jspServlet 时,会传递或创建 9 个与 web 开发相关的对象供 jspServlet 使用。 JSP 技术的设计者为便于开发人员在编写 JSP 页面时获得这些 web 对象的引用,特意定义了 9 个相应的变量,开发人员在JSP页面中通过这些变量就可以快速获得这 9 大对象的引用。
这九个对象,可以不用声明直接使用
变量名 | 类型 | 作用 |
---|---|---|
pageContext | PageContext | 当前页面共享数据,还可以获取其他8个内置对象 |
request | HttpServletRequest | 客户端请求对象,包含了所有客户端请求信息 |
session | HttpSession | 请求会话 |
application | ServletContext | 全局对象,所有用户间共享数据 |
response | HttpServletResponse | 响应对象,主要用于服务器端设置响应信息 |
page | Object | 当前Servlet对象,this |
out | JspWriter | 输出对象,数据输出到页面上 |
config | ServletConfig | Servlet的配置对象 |
exception | Throwable | 异常对象 |
JSP 表达式(EL)
EL(Expression Language),主要用于替换JSP页面中的脚本表达式<%= %>
,在jsp页面中获取请求中的值、执行运算、调用方法等
从request域对象中,取得user这个对象的年龄:
1 |
|
等价于JSP Scriptlet的写法:
1 |
|
有趣的是,它还可以用来执行命令
1 |
|
https://forum.butian.net/share/886
JSP 标准标签库(JSTL)
JSP标准标签库(JSTL)是一个JSP标签集合,它封装了JSP应用的通用核心功能。
JSTL 中常见的标签库:
- 核心标签库 (uri=“http://java.sun.com/jsp/jstl/core")
<c:out>
- 输出字符串<c:if>
- 条件处理<c:forEach>
- 集合遍历
- 格式化标签库 (uri=“http://java.sun.com/jsp/jstl/fmt")
<fmt:message>
- 格式化并显示消息<fmt:formatDate>
- 格式化日期
- SQL 标签库 (uri=“http://java.sun.com/jsp/jstl/sql")
<sql:setDataSource>
- 指定数据源并使其可用于 SQL 操作<sql:query>
- 执行 SQL 查询并迭代结果集<sql:update>
- 通过执行 SQL 语句更新数据源
- XML 标签库(uri=“http://java.sun.com/jsp/jstl/xml")
<x:parse>
- 解析 XML 文档<x:forEach>
- 遍历 XML 文档<x:out>
- 输出结果
- 函数标签库 (uri=“http://java.sun.com/jsp/jstl/functions")
官方文档:https://docs.oracle.com/javaee/5/jstl/1.1/docs/tlddocs/
注意在 Tomcat 或者 Jetty 这种轻量级的容器内使用 JSTL 需要安装对应的依赖
使用JSP
打开IDEA 创建一个Maven archetype 的项目,模板选择webapp 项目,设置名称。还需要配置tomcat
这里的操作和之前servlet一样,就直接拿之前的项目来就好了
然后,需要在src/main/webapp文件夹下创建jsp文件,分别创建login.jsp和do_login.jsp
login.jsp:
1 |
|
do_login.jsp:
1 |
|
如图,然后部署访问/login.jsp
当输入admin/password时,就会跳转到do_login.jsp界面,并显示Success!
带回显的jsp一句话
1 |
|
带密码的一句话
1 |
|
1 |
|