Java拦截器-完成用户登录认证拦截

前言

在完成实习任务时,根据要求系统整体必须使用拦截器进行用户权限权限认证和确认,在此之前,我已完成了通过token完成时限内认证的功能,现接收到新的需求,可以直接添加拦截器,再用拦截器调用我写好的认证模块即可。
为此,我查询了不少在线资料,不少资料很有参考价值,但多数资料不全且可能存在一些问题,我根据我的情况进行了总结,下面进行详细介绍。

拦截器的几种实现方式

使用URL进行拦截

其原理为获取URL后的参数,基于正则表达式,检查URL中必须的参数,如token、用户凭证等。

使用注解的拦截器

同样是创建拦截器,但不再以URL做区分,而是使用Controller作为依据,即使用指定Controller才可出发拦截器。

拦截器实现

下面根据我的项目进行还原,分享拦截器实现过程,在下一章我再对代码进行讲解。

拦截器建立

首先建立两个类,位置随意,分别为MvcInterceptorConfig和LoginInterceptor。具体细节如下:

MvcInterceptorConfig.java

import com.[保密需要,隐去].Utils.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import java.util.concurrent.TimeUnit;

@Configuration
public class MvcInterceptorConfig  extends WebMvcConfigurerAdapter {
    @Autowired
    private LoginInterceptor loginInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
 registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns("/index","/static/**","/","/Common/Message","/visitsys");
        super.addInterceptors(registry);
    }
}

LoginInterceptor.java

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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


@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        SafeUtil safeUtil = new SafeUtil();
        if (!safeUtil.loginTimeOut(request)) {
            response.sendRedirect("/index");
            return false;
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }


    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }

}

静态资源过滤

建立上述两个类后,如果我们直接运行,会发现我们的CSS、js资源都没有加载出来。这是因为静态资源没有正确加载,同样被拦截器拦截。我们自然不希望静态资源同样被拦截器拦截,除非该资源涉密,但诸如css、js之类的无不呈现在用户面前,基本上不涉及秘密。所以我们需要针对这些静态资源予以放行。在上面拦截器建立的时候,代码中已经有白名单,所以我们接下来建立符合该白名单的资源即可。 这个时候,我们就需要修改application.properties(Spring配置文件),在配置文件中,将静态资源路径设置为/static/**,如下所示

spring.mvc.static-path-pattern=/static/**

设置好配置文件并保存后,我们需要将所有静态文件调用路径前加上 /static/,示例:

<script src="/static/jquery-2.0.2.min.js">
<link rel="stylesheet" href="/static/css/layui.css" media="all">
<script src="/static/layui.all.js"></script>

这个时候再访问网页,发现静态资源已经可以正常访问了。

代码详解

我们根据一般实现顺序进行讲解,而非上述补救顺序,所谓一般实现顺序是有策略性的完成整体项目时,会提前构建框架,那么基于一般实现顺序可以更方便的完成后期设计和编程,而补救顺序就如这个教程一样,在没有设计拦截器的时候因为需求变更追加了拦截器,在原有系统上进行修改。那么我们开始吧。

application.properties

spring.mvc.static-path-pattern=/static/**

设置静态资源前缀为/static/,如果不设置,则默认是/,即

spring.mvc.static-path-pattern=/**

如此一来我们无法把静态资源和拦截资源区分开,所以这点必须完成设置。
同时,之后所有静态引用均需要在路径前加入/static/,当然,绝对路径除外。

LoginInterceptor

该类是拦截器,接口HandlerInterceptor,注解为@Component,该注解泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。相当于配置文件中的<bean id="" class=""/>

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    //在此处加入拦截策略
}

该方法为预处理,在Controller被调用前执行,@Return为true则表示继续流程,为false则中断,如果我们希望在false时跳转到登录界面或者其他错误页面,可以在这里设置跳转。

response.sendRedirect("/index");//可以替换为其他要跳转的页面

因为我已经封装了认证,因此在这里没有什么明显的体现,大家可以选择几种认证方式,如
– 获取request进行认证
– 获取season进行认证
– 获取cookie进行认证

其中,我使用的是cookie+加密token的方式进行来了认证,可以控制登录超时时间,在此暂且不提。

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {}

方法实现的时间是在controller 与视图渲染中间,因此他是无法屏蔽controller的过程的,这点需要注意,但我们可以对modelAndView进行处理,比如addObject之类的。

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}

方法实现了请求完毕回调,当视图渲染完毕后回调,不知道这个能干嘛,但还是留着,万一以后能用上呢。

以上是拦截器类的建立,主要完成拦截器的执行时间和执行内容。

MvcInterceptorConfig

此类是完成MVC拦截器配置的类,继承WebMvcConfigurerAdapter,注解为@Configuration,用于定义配置类,可替换xml配置文件。

@Autowired是用在JavaBean中的注解,通过byType形式,用来给指定的字段或方法注入所需的外部资源。

@Autowired
private LoginInterceptor loginInterceptor;

调用LoginInterceptor。

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(loginInterceptor).addPathPatterns("/**")
      .excludePathPatterns("/index","/static/**","/","/Common/Message","/visitsys");
    super.addInterceptors(registry);    //调用父类方法addInterceptors添加拦截器
}

方法用于添加拦截器,其中
– addPathPatterns:添加拦截规则,/**表示所有请求
– excludePathPatterns:拦截白名单,在名单内的不拦截,语法如上所示,注意其中的“/static/**”,结合上述静态资源设置,可以知道这样可以取消静态资源的拦截。

之后我们的拦截器就完成所有配置啦~

Advertisements

容我提两嘴

可惜中文支持不好,留下你的姓名邮箱之后走吧,网站和Email都不会显示,广告党们不用想了,必须审核才能通过显示的。

Advertisements