Java Web
jsp简介:
HTML擅长显示页面,但是它并不能调用Java代码动态的生成内容;Servlet擅长调用Java程序,生成动态内容,但是Servlet不擅长显示页面。
jsp(Java Server Pages)结合了HTML和Servlet的优点,本质上是运行在服务端的一个Servlet,Tomcat等Servlet容器会将jsp文件中的内容通过out.write()、out.print()等方法直接输出给浏览器,浏览器获取到的依然是一个html文档,然后再进行渲染等
JSP基本语法
1、模板元素
模板元素指就是JSP中的HTML代码,模板元素的内容会作为out.write()的参数,直接输出到页面中,在HTML中怎么写,在JSP中就怎么写
2、 脚本片段
脚本片段写在 <% %>中,可以在脚本片段中直接编写Java代码,脚本片段会原封不动的复制到java文件的service方法中的对应位置
3、表达式
JSP的表达式写在<%= %>中,JSP表达式可以将一个对象直接输出到页面中,JSP表达式中的内容最终会作为out.print()方法的参数,输出到页面中
4、注释
JSP的注释写在 <%-- --%>中
5、声明
JSP中的声明写在<%! %>中
6、JSP指令
JSP指令的格式:<%@ 指令名 属性名1=”属性值1” 属性名2=”属性值2” %>,举例:
a、page指令:b、include指令c、taglib指令
7、JSP动作标签格式:
a、请求转发
b、动态包含
64. jsp 和 servlet 有什么区别?
- jsp经编译后就变成了Servlet.(JSP的本质就是Servlet,JVM只能识别java的类,不能识别JSP的代码,Web容器将JSP的代码编译成JVM能够识别的java类)
- jsp更擅长表现于页面显示,servlet更擅长于逻辑控制。
- Servlet中没有内置对象,Jsp中的内置对象都是必须通过HttpServletRequest对象,HttpServletResponse对象以及HttpServlet对象得到。
- Jsp是Servlet的一种简化,使用Jsp只需要完成程序员需要输出到客户端的内容,Jsp中的Java脚本如何镶嵌到一个类中,由Jsp容器完成。而Servlet则是个完整的Java类,这个类的Service方法用于生成对客户端的响应。
65. jsp 的9个内置对象分别是什么?作用是什么?
JSP有9个内置对象:
- request:封装客户端的请求,其中包含来自GET或POST请求的参数;
- response:封装服务器对客户端的响应;
- pageContext:通过该对象可以获取其他对象;
- session:封装用户会话的对象;
- application:封装服务器运行环境的对象;
- out:输出服务器响应的输出流对象;
- config:Web应用的配置对象;
- page:JSP页面本身(相当于Java程序中的this);
- exception:封装页面抛出异常的对象。
66. 说一下 jsp 的 4 种作用域?
JSP中的四种作用域包括page、request、session和application,具体来说:
- pageContext对象,最小的域对象,可以在当前页面中共享数据,一旦切换页面,则域中的属性就会丢失,该对象主要用来向标签中传递数据。
- request对象,可以在一次请求中共享数据,一旦发送多次请求,则域中的属性就会丢失。主要用于在转发时共享数据(request域中属性在转发时有效,重定向时无效)。
- session对象,可以在一次会话中共享数据,一旦会话结束则域中的属性丢失。会话:就是一次打开关闭浏览器的过程。
- application对象,是最大的域对象,作用范围是整个项目,只要不关闭服务器则application域中的属性一直有效。
67. session 和 cookie 有什么区别?
1、存储位置不同
cookie的数据信息存放在客户端浏览器上。session的数据信息存放在服务器上。
2、存储容量不同
单个cookie保存的数据<=4KB,一个站点最多保存20个Cookie。对于session来说并没有上限,但出于对服务器端的性能考虑,session内不要存放过多的东西,并且设置session删除机制。
3、存储方式不同
cookie中只能保管ASCII字符串,并需要通过编码方式存储为Unicode字符或者二进制数据。session中能够存储任何类型的数据,包括且不限于string,integer,list,map等。
4、隐私策略不同
cookie对客户端是可见的,所以它是不安全的。session存储在服务器上,不存在敏感信息泄漏的风险。
5、有效期上不同
可以通过设置cookie的属性,达到使cookie长期有效的效果。Sessinon在用户访问第一次访问服务器时创建,需要注意只有访问JSP、Servlet等程序时才会创建Session,只访问HTML、IMAGE等静态资源并不会创建Session,可调用request.getSession(true)强制生成Session。Tomcat中Session的默认失效时间为20分钟,只需关闭窗口该session就会失效,因而session不能达到长期有效的效果。session的过期时间是从session不活动的时候开始计算(如果session一直活动,session就总不会过期,从该Session未被访问,开始计时; 一旦Session被访问,计时清0);
6、服务器压力不同
cookie保管在客户端,不占用服务器资源。对于并发用户十分多的网站,cookie是很好的选择。session是保管在服务器端的,每个用户都会产生一个session。假如并发访问的用户十分多,会产生十分多的session,耗费大量的内存。
7、浏览器支持不同
假如客户端浏览器不支持cookie:
cookie是需要客户端浏览器支持的,假如客户端禁用了cookie,或者不支持cookie,则会话跟踪会失效。session一般来说要配合cookie使用,如果用户浏览器禁用了cookie,那么只能使用URL重写来实现session的存储功能。
假如客户端支持cookie:
cookie既能够设为本浏览器窗口以及子窗口内有效,也能够设为一切窗口内有效。session只能在本窗口以及子窗口内有效。
8、跨域支持上不同
cookie支持跨域名访问。session不支持跨域名访问。
68. 说一下 session 的工作原理?
session类似于map是键值对的形式存在的。通过session.getAttribute("name");获取对应的name参数信息
当用户访问到一个服务器,如果服务器启用Session,服务器就要为该用户创建一个session,在创建这个session的时候,服务器首先检查这个用户发来的请求里是否包含了一个session id,如果存在就去遍历服务端的session文件,找到与这个session id相对应的文件,文件中的key值便是session id,value为当前用户的一些信息,如果客户端请求里不包含有session id,则为该客户端创建一个session并生成一个与此session相关的session id。这个session id是唯一的、不重复的、不容易找到规律的字符串,这个session id将被在本次响应中返回到客户端保存,而保存这个session id的正是cookie通过set-cookie完成,此后的请求都会交换这个 Session ID,进行有状态的会话。
69. 如果客户端禁止 cookie 能实现 session 还能用吗?
Cookie与 Session,一般认为是两个独立的东西,Session采用的是在服务器端保持状态的方案,而Cookie采用的是在客户端保持状态的方案。
一般默认情况下,在会话中,服务器存储 session 的 session id 是通过 cookie 保存到浏览器里。
如果浏览器禁用了 cookie,浏览器请求服务器无法携带 session id,服务器无法识别请求中的用户身份,session就会失效。
但是可以通过其他方法在禁用 cookie 的情况下,可以继续使用session。
- 通过url重写,把 session id 作为参数追加的原 url 中,后续的浏览器与服务器交互中携带 session id 参数。
- 服务器的返回数据中包含 session id,浏览器发送请求时,携带 session id 参数。
- 通过 Http 协议其他 header 字段,服务器每次返回时设置该 header 字段信息,浏览器中 js 读取该 header 字段,请求服务器时,js设置携带该 header 字段。
70. spring mvc 和 struts 的区别是什么?
- 拦截机制的不同
Struts2是类级别的拦截,每次请求就会创建一个Action,和Spring整合时Struts2的ActionBean注入作用域是原型模式prototype,然后通过setter,getter吧request数据注入到属性。Struts2中,一个Action对应一个request,response上下文,在接收参数时,可以通过属性接收,这说明属性参数是让多个方法共享的。Struts2中Action的一个方法可以对应一个url,而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了,只能设计为多例。
SpringMVC是方法级别的拦截,一个方法对应一个Request上下文,所以方法直接基本上是独立的,独享request,response数据。而每个方法同时又和一个url对应,参数的传递是直接注入到方法中的,是方法所独有的。处理结果通过ModeMap返回给框架。在Spring整合时,SpringMVC的Controller Bean默认单例模式Singleton,所以默认对所有的请求,只会创建一个Controller,有应为没有共享的属性,所以是线程安全的,如果要改变默认的作用域,需要添加@Scope注解修改。
Struts2有自己的拦截Interceptor机制,SpringMVC这是用的是独立的Aop方式,这样导致Struts2的配置文件量还是比SpringMVC大。
- 底层框架的不同
Struts2采用Filter(StrutsPrepareAndExecuteFilter)实现,SpringMVC(DispatcherServlet)则采用Servlet实现。Filter在容器启动之后即初始化;服务停止以后坠毁,晚于Servlet。Servlet在是在调用时初始化,先于Filter调用,服务停止后销毁。
- 性能方面
Struts2是类级别的拦截,每次请求对应实例一个新的Action,需要加载所有的属性值注入,SpringMVC实现了零配置,由于SpringMVC基于方法的拦截,有加载一次单例模式bean注入。所以,SpringMVC开发效率和性能高于Struts2。
- 配置方面
spring MVC和Spring是无缝的。从这个项目的管理和安全上也比Struts2高。
71. 如何避免 sql 注入?
- PreparedStatement(简单又有效的方法)
采用预编译语句集,输出的SQL是把整个参数用引号包起来,并把参数中的引号作为转义字符,从而避免了参数也作为条件的一部分,只要使用它的setXXX方法传值即可
sql注入只对sql语句的准备(编译)过程有破坏作用,PreparedStatement参数不是简单拼接生成sql,而是先用?占位,之后再根据参数产生sql,因此也就避免了sql注入问题
//构建sql语句,以?作为占位符
String sq = "delete from table1 where id=? and name=?"
//创建PreparedStatement时就传入sql语句,实现了预编译
PreparedStatement ps = con.prepareStatement(sq);
//设置sql语句的占位符的值,注意第一个参数位置是1不是0
ps.setString(1,"03");
ps.setString(2,"mao");
//执行这个PreparedStatement
ps.execute();
- 使用正则表达式过滤传入的参数
- 字符串过滤
- JSP中调用该函数检查是否包函非法字符
- JSP页面判断代码
使用javascript在客户端进行不安全字符屏蔽
功能介绍:检查是否含有”‘”,”\”,”/”
72. 什么是 XSS 攻击,如何避免?
XSS攻击又称CSS,全称Cross Site Script (跨站脚本攻击),其原理是攻击者向有XSS漏洞的网站中输入恶意的 HTML 代码,当用户浏览该网站时,这段 HTML 代码会自动执行,从而达到攻击的目的。XSS 攻击类似于 SQL 注入攻击,SQL注入攻击中以SQL语句作为用户输入,从而达到查询/修改/删除数据的目的,而在xss攻击中,通过插入恶意脚本,实现对用户游览器的控制,获取用户的一些信息。 XSS是 Web 程序中常见的漏洞,XSS 属于被动式且用于客户端的攻击方式。
XSS防范的总体思路是:对输入(和URL参数)进行过滤,对输出进行编码。
73. 什么是 CSRF 攻击,如何避免?
CSRF(Cross-site request forgery)也被称为 one-click attack或者 session riding,中文全称是叫跨站请求伪造。一般来说,攻击者通过伪造用户的浏览器的请求,向访问一个用户自己曾经认证访问过的网站发送出去,使目标网站接收并误以为是用户的真实操作而去执行命令。常用于盗取账号、转账、发送虚假消息等。攻击者利用网站对请求的验证漏洞而实现这样的攻击行为,网站能够确认请求来源于用户的浏览器,却不能验证请求是否源于用户的真实意愿下的操作行为。
如何避免:
- 验证 HTTP Referer 字段
HTTP头中的Referer字段记录了该 HTTP 请求的来源地址。在通常情况下,访问一个安全受限页面的请求来自于同一个网站,而如果黑客要对其实施 CSRF
攻击,他一般只能在他自己的网站构造请求。因此,可以通过验证Referer值来防御CSRF 攻击。
- 使用验证码
关键操作页面加上验证码,后台收到请求后通过判断验证码可以防御CSRF。但这种方法对用户不太友好。
- 在请求地址中添加token并验证
CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于cookie中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的cookie 来通过安全验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有token或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。这种方法要比检查 Referer 要安全一些,token 可以在用户登陆后产生并放于session之中,然后在每次请求时把token 从 session 中拿出,与请求中的 token 进行比对,但这种方法的难点在于如何把 token 以参数的形式加入请求。
对于 GET 请求,token 将附在请求地址之后,这样 URL 就变成 http://url?csrftoken=tokenvalue。
而对于 POST 请求来说,要在 form 的最后加上 ,这样就把token以参数的形式加入请求了。
- 在HTTP 头中自定义属性并验证
这种方法也是使用 token 并进行验证,和上一种方法不同的是,这里并不是把 token 以参数的形式置于 HTTP 请求之中,而是把它放到 HTTP 头中自定义的属性里。通过 XMLHttpRequest 这个类,可以一次性给所有该类请求加上 csrftoken 这个 HTTP 头属性,并把 token 值放入其中。这样解决了上种方法在请求中加入 token 的不便,同时,通过 XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,也不用担心 token 会透过 Referer 泄露到其他网站中去。