1.servlet
(1)servlet的定义
运行在服务器端的小程序。是服务器端用来处理客户端请求的组件,需要在web.xml文件中进行配置;是servlet规范中定义的用来处理客户端请求的程序需要实现的顶级接口。
(2)servlet的方法:
Servlet接口定义了5个方法:
//在servlet被创建时执行,只会执行一次
void init(ServletConfig config) throws ServletException
//提供服务方法,每次servlet被访问时执行,可执行多次
void service(ServletRequest req, ServletResponse resp) throws ServletException, java.io.IOException
//在服务器关闭后执行,只执行一次
void destory()
//servlet的配置对象
java.lang.String getServletInfo()
//获取servlet的信息
ServletConfig getServletConfig()
(3)servlet的生命周期
web容器加载servlet,生命周期开始。
(4)servlet与线程安全
Servlet不是线程安全的,多线程并发的读写会导致数据不同步的问题。 解决的办法是尽量不要定义name属性,而是要把name变量分别定义在doGet()和doPost()方法内。虽然使用synchronized(name){}语句块可以解决问题,但是会造成线程的等待,不是很科学的办法。
注意:多线程的并发的读写Servlet类属性会导致数据不同步。但是如果只是并发地读取属性而不写入,则不存在数据不同步的问题。因此Servlet里的只读属性最好定义为final类型的。
(5)servlet和jsp的区别
JSP是Servlet的扩展,本质上是Servlet的简易方式,更强调应用的外表表达。JSP编译后是"类Servlet"。Servlet和JSP最主要的不同点在于,Servlet的应用逻辑是在java文件中,并且完全从表示层中的HTML里分离开来。而JSP的情况是java和HTML可以组合成一个扩展名为.jsp的文件。JSP偏重于视图,Servlet偏重于业务逻辑。
2.get和post请求的区别
(1)get是用来从服务器上获取数据,而post是用来向服务器传递数据;
(2)get将表单中数据按照variable=value的形式,添加到action所指向的URL后面,并且两者用"?“连接,变量之间用”&"连接;而post是将表单中的数据放在form的数据体中,按照变量与值对应的方式,传递到action所指定的URL。
(3)get是不安全的,因为在传输过程中,数据是被放在请求的URL中;而post的所有操作对用户来说都是不可见的。
(4)get传输的数据量小,这主要应为受url长度限制;而post可以传输大量的数据,所有上传文件只能用post提交。
(5)get限制form表单的数据集必须为ASCII字符;而post支持整个IS01 0646字符集。
(6)get是form表单的默认方法。
3. 转发和重定向的区别
(1)转发(forward):转发是服务器端行为。
地址栏不变:服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器。
数据共享:转发是一次请求,转发页面和转发到的页面可以共享request里面的数据。
数据访问:只能访问当前服务器的资源。
request.getRequestDispatcher("login_success.jsp").forward(request, response);
(2)重定向(redirect):重定向是客户端行为。
地址栏变化:服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,所以地址栏显示的是新的URL。
数据不共享:重定向是多次请求,不能使用request对象共享数据。
数据访问:可以访问其他站点(服务器)的资源。
4. JSP
(1)工作原理
JSP是一种Servlet,但是与HttpServlet的工作方式不太一样。HttpServlet是先由源代码编译为class文件后部署到服务器下,为先编译后部署。而JSP则是先部署后编译。工程JspLoginDemo下有一个名为login.jsp的Jsp文件,把工程第一次部署到服务器上后访问这个Jsp文件,我们发现这个目录下多了下图这两个东东。.class文件便是JSP对应的Servlet。编译完毕后再运行class文件来响应客户端请求。以后客户端访问login.jsp的时候,Tomcat将不再重新编译JSP文件,而是直接调用class文件来响应客户端请求。
由于JSP只会在客户端第一次请求的时候被编译 ,因此第一次请求JSP时会感觉比较慢,之后就会感觉快很多。如果把服务器保存的class文件删除,服务器也会重新编译JSP。
(2)JSP内置对象:有9个内置对象。
request:负责得到客户端请求的信息,对应类型:javax.servlet.http.HttpServletRequest
response:负责向客户端发出响应,对应类型:javax.servlet.http.HttpServletResponse
session:负责保存同一客户端一次会话过程中的一些信息,对应类型:javax.servlet.http.httpsession
out:负责管理对客户端的输出,对应类型:javax.serlvet.jsp.jspwriter
application:表示整个应用环境的信息,对应类型:javax.servlet.servletcontext
config:表示ServletConfig,对应类型:javax.servlet.servletconfig
exception:表示页面中发生的异常,可以通过它获得页面异常信息,对应类型:java.lang.exception
pagecontext:表示这个JSP页面上下文,对应类型:javax.servlet.jsp.pagecontext
page:表示当前JSP页面本身。
(3)JSP的动作:有6个基本动作。
(4)JSP常用指令:page、include、taglib
(5)JSP中的四种作用域:page、request、session和application。
(6)解决JSP乱码
5.request
(1)request:request对象是由服务器创建的,request对象用来获取请求消息。
(2)request对象的主要方法:
setAttribute(String name,Object):设置名字为name的request 的参数值
getAttribute(String name):返回由name指定的属性值
getAttributeNames():返回request 对象所有属性的名字集合,结果是一个枚举的实例
getCookies():返回客户端的所有 Cookie 对象,结果是一个Cookie 数组
getCharacterEncoding() :返回请求中的字符编码方式 = getContentLength() :返回请求的 Body的长度
getHeader(String name) :获得HTTP协议定义的文件头信息
getHeaders(String name) :返回指定名字的request Header 的所有值,结果是一个枚举的实例
getHeaderNames() :返回所以request Header 的名字,结果是一个枚举的实例
getInputStream() :返回请求的输入流,用于获得请求中的数据
getMethod() :获得客户端向服务器端传送数据的方法
getParameter(String name) :获得客户端传送给服务器端的有 name指定的参数值
getParameterNames() :获得客户端传送给服务器端的所有参数的名字,结果是一个枚举的实例
getParameterValues(String name):获得有name指定的参数的所有值
getProtocol():获取客户端向服务器端传送数据所依据的协议名称
getQueryString() :获得查询字符串
getRequestURI() :获取发出请求字符串的客户端地址
getRemoteAddr():获取客户端的 IP 地址
getRemoteHost() :获取客户端的名字
getSession([Boolean create]) :返回和请求相关 Session
getServerName() :获取服务器的名字
getServletPath():获取客户端所请求的脚本文件的路径
getServerPort():获取服务器的端口号
removeAttribute(String name):删除请求中的一个属性
(3)request.getAttribute()和 request.getParameter()有何区别?
6. 实现会话跟踪技术的方法
(1) Cookie:客户端会话技术,将数据保存在客户端。
优点: 数据可以持久保存,不需要服务器资源,简单,基于文本的Key-Value。
缺点: 大小受到限制,用户可以禁用Cookie功能,由于保存在本地,有一定的安全风险。
向客户端发送Cookie:
Cookie c =new Cookie("name","value"); //创建Cookie
c.setMaxAge(60*60*24); //设置最大时效,此处设置的最大时效为一天
response.addCookie(c); //把Cookie放入到HTTP响应中
从客户端读取Cookie:
String name ="name";
Cookie[]cookies =request.getCookies();
if(cookies !=null){
for(int i= 0;i<cookies.length;i++){
Cookie cookie =cookies[i];
if(name.equals(cookis.getName())) {
cookie.getValue();
}
}
}
(2) URL 重写:在URL中添加用户会话的信息作为请求的参数,或者将唯一的会话ID添加到URL结尾以标识一个会话。
优点: 在Cookie被禁用的时候依然可以使用。
缺点: 必须对网站的URL进行编码,所有页面必须动态生成,不能用预先记录下来的URL进行访问。
(3) 隐藏的表单域
<input type="hidden" name ="session" value="..."/>
优点: Cookie被禁时可以使用。
缺点: 所有页面必须是表单提交之后的结果。
(4) HttpSession:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中。
在所有会话跟踪技术中,HttpSession对象是最强大也是功能最多的。当一个用户第一次访问某个网站时会自动创建 HttpSession,每个用户可以访问他自己的HttpSession。可以通过HttpServletRequest对象的getSession方法获得HttpSession,通过HttpSession的setAttribute方法可以将一个值放在HttpSession中,通过调用 HttpSession对象的getAttribute方法,同时传入属性名就可以获取保存在HttpSession中的对象。
与上面三种方式不同的是,HttpSession放在服务器的内存中,因此不要将过大的对象放在里面,即使目前的Servlet容器可以在内存将满时将HttpSession 中的对象移到其他存储设备中,但是这样势必影响性能。添加到HttpSession中的值可以是任意Java对象,这个对象最好实现了 Serializable接口,这样Servlet容器在必要的时候可以将其序列化到文件中,否则在序列化时就会出现异常。
7. cookie和session的区别
(1) 由于HTTP协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识具体的用户,这个机制就是Session.典型的场景比如购物车,当你点击下单按钮时,由于HTTP协议无状态,所以并不知道是哪个用户操作的,所以服务端要为特定的用户创建了特定的Session,用用于标识这个用户,并且跟踪用户,这样才知道购物车里面有几本书。这个Session是保存在服务端的,有一个唯一标识。在服务端保存Session的方法很多,内存、数据库、文件都有。集群的时候也要考虑Session的转移,在大型的网站,一般会有专门的Session服务器集群,用来保存用户会话,这个时候 Session 信息都是放在内存的,使用一些缓存服务比如Memcached之类的来放 Session。
(2) 每次HTTP请求的时候,客户端都会发送相应的Cookie信息到服务端。实际上大多数的应用都是用 Cookie 来实现Session跟踪的,第一次创建Session的时候,服务端会在HTTP协议中告诉客户端,需要在 Cookie 里面记录一个Session ID,以后每次请求把这个会话ID发送到服务器,我就知道你是谁了。如果客户端的浏览器禁用了 Cookie ,使用一种叫做URL重写的技术来进行会话跟踪,即每次HTTP交互,URL后面都会被附加上一个诸如 sid=xxxxx 这样的参数,服务端据此来识别用户。
(3) Cookie其实还可以用在一些方便用户的场景下,设想你某次登陆过一个网站,下次登录的时候不想再次输入账号了,怎么办?总结一下:Session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中,session相对安全,没有大小限制;Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式,cookie相对不安全,有大小限制。
8. MVC
基于java的web应用系统采用MVC设计模型,即用Model(模型)、View(视图)和Controller(控制)分离设计,这是目前web应用服务系统的主流设置方向。
9. 避免 sql 注入的方法
(1)PreparedStatement
采用预编译语句集,它内置了处理SQL注入的能力,只要使用它的setXXX方法传值即可。
原理:sql注入只对sql语句的准备(编译)过程有破坏作用,而PreparedStatement已经准备好了,执行阶段只是把输入串作为数据处理,而不再对sql语句进行解析,准备,因此也就避免了sql注入问题。
(2)使用正则表达式过滤传入的参数
(3)字符串过滤
(4)jsp中调用该函数检查是否包函非法字符
(5)JSP页面判断代码
10.XSS 攻击,如何避免
(1)XSS 攻击,即跨站脚本攻击(Cross Site Scripting),它是 web 程序中常见的漏洞。
(2)原理:攻击者往 web 页面里插入恶意的 HTML 代码(Javascript、css、html 标签等),当用户浏览该页面时,嵌入其中的 HTML 代码会被执行,从而达到恶意攻击用户的目的。如盗取用户 cookie 执行一系列操作,破坏页面结构、重定向到其他网站等。
(3)预防:
a:web 页面中可由用户输入的地方,如果对输入的数据转义、过滤处理。
b:后台输出页面的时候,也需要对输出内容进行转义、过滤处理(因为攻击者可能通过其他方式把恶意脚本写入数据库)。
c:前端对 html 标签属性、css 属性赋值的地方进行校验。
11. CSRF 攻击,如何避免
(1)CSRF(Cross-site request forgery)跨站请求伪造,也被称为 one-click attack或者 session riding。
(2)原理:攻击者通过伪造用户的浏览器请求,将请求发送到用户自己曾经认证访问过的网站,使目标网站接收并误以为是用户的真实操作而去执行命令。常用于盗取账号、转账、发送虚假消息等。
(3)防范:
a:验证 HTTP Referer 字段
HTTP头中的Referer字段记录了该 HTTP 请求的来源地址。在通常情况下,访问一个安全受限页面的请求来自于同一个网站,而如果黑客要对其实施 CSRF攻击,他一般只能在他自己的网站构造请求。因此,可以通过验证Referer值来防御CSRF 攻击。
b:使用验证码
关键操作页面加上验证码,后台收到请求后通过判断验证码可以防御CSRF。但这种方法对用户不太友好。
c:在请求地址中添加token并验证
在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有token或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。这种方法要比检查 Referer 要安全一些,token 可以在用户登陆后产生并放于session之中,然后在每次请求时把token 从 session 中拿出,与请求中的 token 进行比对,但这种方法的难点在于如何把 token 以参数的形式加入请求。
http://url?csrftoken=tokenvalue。
,这样就把token以参数的形式加入请求了。d:在HTTP 头中自定义属性并验证
通过 XMLHttpRequest 这个类,可以一次性给所有该类请求加上 csrftoken 这个 HTTP 头属性,并把 token 值放入其中。这样解决了上种方法在请求中加入 token 的不便,同时,通过 XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,也不用担心 token 会透过 Referer 泄露到其他网站中去。