java实现interceptor拦截登录权限

 更新时间:2023年09月16日 08:59:47   作者:Java小卷  
Java里的拦截器是动态拦截action调用的对象,本文主要介绍了java实现interceptor拦截登录权限,具有一定的参考价值,感兴趣的可以了解一下

前面我们对某些请求url中的处理逻辑前加了身份验证和权限检查,我们采用最low的形式:每个方法中自己判断一遍,本节我们将使用另一种拦截机制来实现统一的登录权限拦截。

我们只希望拦截一些需要检查的controller请求url,而对于其他资源的请求都不拦截;并且我们希望在拦截处理逻辑中抛出异常的情况下,最终可以被处理目标controller执行方法的异常处理器所处理。因此,基于这样的需求,我们很显然想到用spring mvc家族中的重要一员——interceptor(拦截器)。

定义拦截器

这里我们没有实现拦截器接口HandlerInterceptor,因为用HandlerInterceptorAdapter的好处是,我们只需要关注要重写的方法:

package com.xiaojuan.boot.web.interceptor;
import ...
public class BasicAuthInterceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return super.preHandle(request, response, handler);
    }
}

实现BasicAuthInterceptor

package com.xiaojuan.boot.web.interceptor;
import ...
@Slf4j
public class BasicAuthInterceptor extends HandlerInterceptorAdapter {
    private final List<String> needLoginUrlPatterns;
    private final List<String> needAdminRoleUrlPatterns;
    private AntPathMatcher antPathMatcher;
    @Resource
    private UserService userService;
    public BasicAuthInterceptor() {
        needLoginUrlPatterns = new ArrayList<>();
        needAdminRoleUrlPatterns = new ArrayList<>();
        needLoginUrlPatterns.add("/user/profile");
        needLoginUrlPatterns.add("/user/signature");
        needLoginUrlPatterns.add("/admin/**");
        // 是needLoginUrlPatterns的子集
        needAdminRoleUrlPatterns.add("/admin/**");
        antPathMatcher = new AntPathMatcher();
    }
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String uri = request.getRequestURI();
        UserInfoDTO userInfo = (UserInfoDTO) WebRequestUtil.getSessionAttribute(SessionConst.LOGIN_USER);
        if (matchUri(uri, needLoginUrlPatterns) && userInfo == null) {
            throw new BusinessException("需要登录才能访问", BusinessError.NO_LOGIN.getValue());
        }
        if (matchUri(uri, needAdminRoleUrlPatterns)) {
            userService.checkAdminRole(userInfo.getRole(), null);
        }
        return true;
    }
    private boolean matchUri(String uri, List<String> patterns) {
        for (String pattern : patterns) {
            if (antPathMatcher.match(pattern, uri)) return true;
        }
        return false;
    }
}

代码说明

对于要过滤的请求地址,这里我们维护了两个列表,一个代表所有要登录检查的url模式,一个代表在登录前提下要检查的管理员角色url模式,很显然,后者是前者的子集。
我们可以在当前类中直接注入需要的服务组件UserService,因为我们将会用@Bean的形式来实例化它,把它注册到Spring容器中。
这里的请求url的模式匹配,我们使用了AntPathMatcher类,比如我们可以用这种模式:/**/admin/**来匹配/juan_mall/product/admin/category/add这样的请求uri。
拦截到目标请求后,我们要在实际业务处理前,先做一些校验工作,可以重写HandlerInterceptor的preHandle方法,该方法如果校验失败,我们可以返回false,也可以抛出异常,如果请求url匹配到目标controller方法,会被拦截的全局异常处理器处理。只要返回true则表示放行,会由后面的controller来处理。

配置拦截器

定义一个WebConfig配置类,在其中通过@Bean注解一个实例化bean的方法,从而让实例化出来的bean交给spring容器管理,这样我们就可以在BasicAuthInterceptor中注入其他bean依赖了。

package com.xiaojuan.boot.web;
import ...
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Bean
    public BasicAuthInterceptor basicAuthInterceptor() {
        return new BasicAuthInterceptor();
    }
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(basicAuthInterceptor()).addPathPatterns("/user/**", "/admin/**");
    }
}

然后,我们实现WebMvcConfigurer的addInterceptors来注册拦截器,并指定拦截器要拦截的请求路径模式。

调整并测试controller

现在我们将UserController和UserAdminController中相关方法进行逻辑简化,只需要关注session中内容的存取,改造的代码这里省略。最后我们测试下WebControllerTest,测试ok!

存在的问题

现在我们来思考下,我们之前的实现中,有哪些可以改进或者存在问题的地方。
很显然,拦截器要拦截的url模式、需要登录才能访问的请求url模式和需要管理员角色才能访问的请求url模式,这些最好配置起来,也就是说,我们可以把它们配置到application.yml中,这是一个可以改进的点。

全局异常处理可能失效

使用拦截器,有一个需要注意的坑,当我们的请求地址无法映射到目标的controller服务方法,也就是,是一个无效的请求地址,发过来被拦截器拦截抛出异常后,无法被异常处理器接管时,会默认返回500的错误格式,如下:

说明我们的全局异常处理还是存在漏洞的,下一节我们将修复试着修复这个漏洞,实现一个更强大的全局异常处理方案

controller日志切面失效

当请求被拦截后如果不放行,也就是说,没机会执行controller,那么自然针对controller方法执行的切面就不会生效,因为压根儿就没执行目标的controller方法,自然我们先前的WebLogAspect就不能工作了:

所以说,针对controller的aop日志输出也是存在漏洞的,因为一些通过filter或interceptor的前置校验不通过,不会往后面的controller走,这也是我们要修复的问题。

到此这篇关于java实现interceptor拦截登录权限的文章就介绍到这了,更多相关java interceptor拦截登录权限内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MyBatis动态SQL标签的用法详解

    MyBatis动态SQL标签的用法详解

    这篇文章主要介绍了MyBatis动态SQL标签的用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • SpringBoot访问不到controller的解决方案

    SpringBoot访问不到controller的解决方案

    这篇文章主要介绍了SpringBoot访问不到controller的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • Java+Nginx实现POP、IMAP、SMTP邮箱代理服务

    Java+Nginx实现POP、IMAP、SMTP邮箱代理服务

    本篇文章的内容是介绍Java+Nginx如何实现POP、IMAP、SMTP邮箱代理服务,步骤详细,思路清新,需要的朋友可以参考下
    2015-07-07
  • 深入讲解基于JDK的动态代理机制

    深入讲解基于JDK的动态代理机制

    众所周知相比于静态代理,动态代理避免了开发人员编写各个繁锁的静态代理类,下面这篇文章主要给大家介绍了关于基于JDK的动态代理机制的相关资料,文中通过图文以及示例代码介绍的非常详细,需要的朋友可以参考下
    2018-07-07
  • mybatis-plus分页查询的实现示例

    mybatis-plus分页查询的实现示例

    这篇文章主要介绍了mybatis-plus分页查询的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • JAVA实现账户取款和存款操作

    JAVA实现账户取款和存款操作

    这篇文章主要介绍了JAVA实现账户取款和存款操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • java开发中基于JDBC连接数据库实例总结

    java开发中基于JDBC连接数据库实例总结

    这篇文章主要介绍了java开发中基于JDBC连接数据库的方法,以实例形式较为详细的总结分析了Java使用JDBC的具体步骤与注意事项,并附带了一个完整实例加以说明,需要的朋友可以参考下
    2015-11-11
  • JVM 运行时数据区与JMM 内存模型

    JVM 运行时数据区与JMM 内存模型

    这篇文章主要介绍了JVM 运行时数据区与JMM 内存模型,文章围绕主题展开详细的内容介绍,具有一定的参考价值。需要的朋友可以参考一下
    2022-07-07
  • java打印从1到100的值(break,return断句)

    java打印从1到100的值(break,return断句)

    java 先写一个程序,打印从1到100的值。之后修改程序,通过使用break关键词,使得程序在打印到98时退出。然后尝试使用return来达到相同的目的
    2017-02-02
  • Spring中的singleton和prototype的实现

    Spring中的singleton和prototype的实现

    这篇文章主要介绍了Spring中的singleton和prototype的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07

最新评论