1

SpringMVC 07: WEB-INF下的资源访问 + SpringMVC拦截器 - nefu_wangxun

 1 year ago
source link: https://www.cnblogs.com/nefu-wangxun/p/16652364.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

WBE-INF目录下的资源访问

  • 项目配置和Spring博客集(指SpringMVC 02)中配置一样

  • 出于对网站资源的安全性保护,放在WBE-INF目录下的资源不可以被外部直接访问

  • 在WEB-INF/jsp/下新建index.jsp和main.jsp,作为WEB-INF目录下的资源

  • 部署并启动tomcat,根据2个资源的位置,尝试直接在地址栏访问

  • 结果如下,两个资源均访问不到

image
  • 修改springmvc.xml中视图解析器如下
    <!-- 添加视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 配置前缀-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!-- 配置后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>
  • 新增控制器:WebInFAction,两个action方法分别转发请求WEB-INF下的相应资源
package com.example.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class WebInfAction {

    @RequestMapping("/showIndex")
    public String showIndex(){
        return "index";
    }

    @RequestMapping("/showMain")
    public String showMain(){
        return "main";
    }
}

  • 分别访问localhost:8080/showIndex.action和localhost:8080/showMain.action,成功访问WEB-INF下的资源
image
  • 由于在web.xml中配置了接受处理的请求的格式"*.action",所以如果请求想要被处理必须以".action"结尾,修改该请求通配条件为"/",即对所有请求都接受处理
  • 分别访问localhost:8080/showIndex和localhost:8080/showMain,去掉访问后缀后,也可以成功访问WEB-INF下的资源
image
  • 虽然通过action转发比直接输入资源地址要安全一些,但是如果直接输入:localhost:8080/showMain也可以直接访问到WEB-INF下的资源,所以上述经action方法转发的方式其实也不安全。
  • 我们尝试增加一个登陆验证,使得只有登陆成功的用户才可以访问到WEB-INF下的main.jsp资源
  • webapp/index.jsp:点击超链接,向服务器请求登陆页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>index.jsp</title>
</head>
<body>
<a href="${pageContext.request.contextPath}/showLogin">去登陆</a>
</body>
</html>
  • WEB-INF/jsp/新增login.jsp:作为登陆页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>login.jsp</title>
</head>
<body>

<!-- 完成登陆信息的提交 -->
    
<h1>登陆</h1>
<form action="${pageContext.request.contextPath}/login" method="post">
    用户名:<input type="text" name="username">
    密码:<input type="password" name="password">
    <input type="submit" value="提交">
</form>
    
<!-- 如果登陆失败,显示登陆失败信息-->
${msg}
    
</body>
</html>
  • 控制器WebInfAction如下:新增登陆页面的转发功能,以及对登陆信息的验证判断功能
package com.example.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;

@Controller
public class WebInfAction {

    @RequestMapping("/showIndex")
    public String showIndex(){
        return "index";
    }

    @RequestMapping("/showMain")
    public String showMain(){
        return "main";
    }

    @RequestMapping("/showLogin")
    public String showLogin(){
        return "login";//转发并返回登陆页面
    }

    //对登陆信息进行判断,用户信息符合是转发跳转到main.jsp,信息不符合时,填入登陆失败的信息并重新转发到登陆页面
    @RequestMapping("/login")
    public String login(String username, String password, HttpServletRequest request){
        if(username.equals("荷包蛋") && password.equals("hebaodan")){
            return "main";
        }else{
            request.setAttribute("msg", "用户名或密码错误");
            return "login";
        }
    }
}
  • 部署并启动tomcat测试
  • 当登陆信息错误时
image
  • 当登陆信息正确时
image
  • 但是如果直接访问:localhost:8080/showMain,仍然可以越过登陆,直接访问WEB-INF下的资源,仍然不安全

SpringMVC拦截器

  • 拦截器执行原理
image
  • 拦截器的作用:

  • 针对请求和响应进行额外的处理,在请求和响应的过程中添加预处理,后处理和最终处理

  • 拦截器执行的时机:

  • preHandle():在请求被处理之前进行操作,即预处理

  • postHandle():在请求被处理之后,但结果还没有渲染前进行操作,可以改变响应结果,即后处理

  • afterCompletion:所有的请求响应结束后执行善后工作,清理对象,关闭资源,即最终处理

  • 拦截器实现的两种方式:

  • 继承HandlerInterceptorAdapter父类

  • 或者实现HandlerInterceptor接口(推荐使用接口方式:java遵循单继承,不要轻易的去继承那些非核心业务的父类,否则就无法再继承其他业务类了,对于某些附加功能,去实现相应接口就可以了,因为允许实现很多接口)

  • 拦截器的实现步骤:

  • 改造登陆方法,在session中存储用户信息,用于进行权限验证

  • 开发拦截器的功能,实现HandlerInterceptor接口,重写preHandle()方法,进行登陆信息验证

  • 在springmvc.xml文件中注册拦截器

  • 使用拦截器继续改造上述WEB-INF下资源的安全访问:

  • WebInfAction中的login方法修改如下:登陆成功后,向session域中存放用户信息,用于后续安全验证

    @RequestMapping("/login")
    public String login(String username, String password, HttpServletRequest request){
        if(username.equals("荷包蛋") && password.equals("hebaodan")){
            //如果登陆成功,则设置session信息
            request.getSession().setAttribute("user", username);
            return "main";
        }else{
            request.setAttribute("msg", "用户名或密码错误");
            return "login";
        }
    }
  • 新增登陆拦截器
package com.example.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 登陆拦截器
 */
public class LoginInterceptor implements HandlerInterceptor {
    //预处理拦截
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //验证session信息,判断是否登陆成功
        if(request.getSession().getAttribute("user") == null){
            request.setAttribute("msg", "还未登陆,清先登陆");
            //打回登陆页面(页面转发实现页面跳转)
            request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
            return false;//验证信息未通过
        }
        return true;//验证信息通过,放行
    }
}
  • 在springmvc.xml中新增对拦截器的注册
    <!-- 配置SpringMVC拦截器-->
    <mvc:interceptors>
        <!-- 可以配置多个拦截规则,形成拦截链-->
        <mvn:interceptor>
            <!-- 映射要拦截的请求:所有请求-->
            <mvn:mapping path="/**"/>
            <!-- 设置要放行的请求:有些必备的登陆请求不能拦截-->
            <mvn:exclude-mapping path="/showLogin"/>
            <mvn:exclude-mapping path="/login"/>
            <!-- 配置实现拦截器功能的实现类-->
            <bean class="com.example.interceptor.LoginInterceptor"/>
        </mvn:interceptor>
    </mvc:interceptors>
  • 部署并启动tomcat测试
  • 当越过登陆直接访问WEB-INF下的资源时,未能通过验证,被打回登陆页面
image
  • 登陆成功后,新建窗口,直接访问,此时session域中信息还未过期,成功通过验证
image

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK