SpringMVC拦截器在用户登录权限中的应用

Posted nuist__NJUPT

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringMVC拦截器在用户登录权限中的应用相关的知识,希望对你有一定的参考价值。

SpringMVC拦截器在用户登录权限中的应用

在开发一个网站时可能有这样的需求,某些页面只希望有几个特定的用户浏览,对于这样的访问权限,该如何实现呢?拦截器就可以实现上述需求。

SpringMVC的拦截器和Java Servlet的过滤器类似,它主要用于拦截用户的请求并作相应的处理,通常应用在权限验证,记录请求日志信息,判断用户是否登录等功能。

SpringMVC框架中定义一个拦截器需要对拦截器进行定义和配置,定义一个拦截器可以通过两种方式:一种是通过实现HandlerInterceptor接口或者继承HandlerInterceptor接口实现类来定义,另一种是实现WebRequestInterceptor接口或者继承该接口的实现类来定义。

在拦截器定义若实现HandleInterceptor接口,需要实现接口中的三个方法:
preHandle方法:该方法在控制器的处理请求方法之前执行,返回值表示是否中断后序操作。true:继续执行,false:中断
postHandle方法:该方法在控制器的处理请求方法调用之后,解析视图之前执行,可以通过此方法对请求域中的模型和视图做进一步的修改。
afterCompletion方法:该方法中控制器的请求处理方法完成之后执行,即视图渲染结束后执行,可以通过该方法实现资源清理,记录日志信息等工作。

让自定义的拦截器生效,需要在SpringMVC的配置文件中进行配置,需要定义拦截器类,拦截器的作用路径。

单个拦截器的执行流程:
执行preHandle–>执行postHandle–>返回视图后执行afterCompletion。

下面通过使用拦截器完后一个用户登录权限验证的web应用。
要求:只有登录的用户才能访问系统的主页面main.jsp,如果没有登录成功而直接访问主页面,则应使用拦截器进行拦截,并转发到登录页面,当登录用户点击退出链接时回到登录页面。
1-创建web应用,在WEB-INF目录下创建lib目录,在该目录下导入相关包。
2-在WEB-INF目录下创建目录jsp,在该目录创建登录页面login.jsp和主页面main.jsp

<%--
  Created by IntelliJ IDEA.
  User: nuist__NJUPT
  Date: 2021/9/30
  Time: 19:35
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>$Title$</title>
</head>
<body>
${msg}
<form action="${pageContext.request.contextPath}/login" method="post">
    用户名:<input type = "text" name = "uname"/> <br>
    密码:<input type = "password" name = "upwd"/> <br>
    <input type = "submit" value = "登录"/>
</form>
</body>
</html>

<%--
  Created by IntelliJ IDEA.
  User: nuist__NJUPT
  Date: 2021/9/30
  Time: 20:12
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
当前用户:${user.uname}<br>
<a href = "${pageContext.request.contextPath}/logout">退出</a>
</body>
</html>

3-在src目录下创建User类,用于向控制器中传递参数。


public class User {
    private String uname ;
    private String upwd ;

    public String getUname() {
        return uname;
    }

    public void setUname(String uname) {
        this.uname = uname;
    }

    public String getUpwd() {
        return upwd;
    }

    public void setUpwd(String upwd) {
        this.upwd = upwd;
    }
}

4-在src目录下创建包controller,在该包中创建控制器类,用于处理登录和退出功能。


import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import pojo.User;

import javax.servlet.http.HttpSession;

@Controller
public class UserController {
    //d登录页面初始化
    @RequestMapping("/toLogin")
    public String initLogin(){
        return "login" ;
    }
    //处理登录功能
    @RequestMapping("/login")
    public String login(User user, Model model, HttpSession session){
        if("wgd".equals(user.getUname()) && "123".equals(user.getUpwd())){
            session.setAttribute("user", user);
            return "redirect:main" ;
        }
        model.addAttribute("msg", "用户名或密码错误") ;
        return "login" ;
    }
    //跳转到主页面
    @RequestMapping("/main")
    public String toMain(){
        return "main" ;
    }
    //退出登录
    @RequestMapping("/logout")
    public String logout(HttpSession session){
        //清除session
        session.invalidate();
        return "login" ;
    }
}

5-在src目录下创建interceptor包,在该包中创建拦截器类进行拦截。

import org.springframework.web.servlet.HandlerInterceptor;

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

public class LoginInterceptor implements HandlerInterceptor {
    //在控制器执行处理之前执行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
       //获取请求的url
        String url = request.getRequestURI() ;
        if(url.indexOf("/toLogin") >= 0|| url.indexOf("/login") >= 0){ //初始化登录,或者登录,则不拦截
            return true ;
        }
        HttpSession session = request.getSession() ;
        Object obj = session.getAttribute("user") ;
        if(obj != null){
            return true ;
        }
        //没有登录,且不是登录页面,则转发到登录页面
        request.setAttribute("msg", "还未登录,请先登录!");
        request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
        return false ;
    }
}

6-在web.xml中配置DispatcherServlet,用于整体控制。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         id = "WebApp_ID" version="4.0">
    <!--部署DispatcherServlet-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>WEB-INF/springmvc-servlet.xml</param-value>
        </init-param>
        <!--表示容器启动时加载的servlet-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <!--任意的请求都通过DispatcherServlet-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!-- 配置 CharacterEncodingFilter解决中文乱码问题-->
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

        <!-- 配置编码格式为UTF-8 -->
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>


7-在WEB-INF下创建配置文件springmvc-servlet.xml,在配置文件中配置拦截器,同时controller包,使注解生效。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--使用扫描机制,扫描控制器类-->
    <context:component-scan base-package="controller"/>
    <mvc:annotation-driven />
    <!--annotation-driven用于简化开发的配置,注解DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter-->
    <!--使用resources过滤掉不需要dispatcherservlet的资源,例如静态资源,在使用resources时必须使用annotation-driven,否则resources会阻止任意控制器被调用-->

    <!--配置视图解析器-->
    <bean class = "org.springframework.web.servlet.view.InternalResourceViewResolver" id = "internalResourceViewResolver">
        <!--前缀-->
        <property name = "prefix" value = "/WEB-INF/jsp/"/>
        <!--后缀-->
        <property name = "suffix" value = ".jsp"/>
    </bean>
    <mvc:interceptors>
        <!--配置拦截器的作用路径为任意路径-->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class = "interceptor.LoginInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
</beans>


8-发布并测试应用。

以上是关于SpringMVC拦截器在用户登录权限中的应用的主要内容,如果未能解决你的问题,请参考以下文章

简单使用拦截器

spring mvc的拦截器的posthandle怎么用

SpringMVC——拦截器异常处理机制

SpingBoot 拦截器的实现(登录拦截简单实现)

SpingBoot 拦截器的实现(登录拦截简单实现)

八 SpringMVC拦截器登录验证