Springboot 拦截器,拦截所有请求,判断是否登录,验证权限

Java的三大器

拦截器的作用

Java里的拦截器是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一个Action执行的前后执行一段代码,也可以在一个Action执行前阻止其执行,同时也提供了一种可以提取Action中可重用部分代码的方式。

功能:可以进行权限验证,审计日志等。

代码实现

拦截器配置类

package com.thk.Interceptor;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 拦截器的属性配置
 *
 */
@Configuration
public class InterceptorConfiguration implements WebMvcConfigurer {


    /**
     * 重写addCorsMappings()解决跨域问题
     * 配置:允许http请求进行跨域访问
     *
     * @param registry
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        //指哪些接口URL需要增加跨域设置
        registry.addMapping("/**")
                //.allowedOrigins("*")//指的是前端哪些域名被允许跨域
                .allowedOriginPatterns("*")
                //需要带cookie等凭证时,设置为true,就会把cookie的相关信息带上
                .allowCredentials(true)
                //指的是允许哪些方法
                .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
                //cookie的失效时间,单位为秒(s),若设置为-1,则关闭浏览器就失效
                .maxAge(3600);
    }
 
    /**
     * 重写addInterceptors()实现拦截器
     * 配置:要拦截的路径以及不拦截的路径
     *
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //注册Interceptor拦截器(Interceptor这个类是我们自己写的拦截器类)
        InterceptorRegistration registration = registry.addInterceptor(new Interceptor());
        //addPathPatterns()方法添加需要拦截的路径
        //所有路径都被拦截
        registration.addPathPatterns("/**");
        //excludePathPatterns()方法添加不拦截的路径
        //添加不拦截路径
        registration.excludePathPatterns(
                //登录
                "/login",
                //退出登录
                "/loginOut",
                //获取验证码
                "/getCode",
                //发送短信
                "/sendshortMessage",
                //重置账号
                "/unsealaccount",
                //文件上传
                "/uploadImg",
                //html静态资源
                "/**/*.html",
                //js静态资源
                "/**/*.js",
                //css静态资源
                "/**/*.css"
        );
    }
}

拦截器实现类

package com.thk.Interceptor;

import com.thk.controller.base.BaseController;
import com.thk.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;

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

/**
 * 拦截器
 */
public class Interceptor extends BaseController implements HandlerInterceptor {

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 在请求处理之前进行调用(Controller方法调用之前)
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        try {
            //判断是否登录
            boolean verifyPermissions = verifyPermissions(request);
            //判断是否有权限
            boolean competence = competence(request);
            if (verifyPermissions && competence) {
                return true;
            }
            //这里设置拦截以后重定向的页面,一般设置为登陆页面地址
            response.sendRedirect(request.getContextPath() + "/error.html");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;//如果设置为false时,被请求时,拦截器执行到此处将不会继续操作
        //如果设置为true时,请求将会继续执行后面的操作
    }
}

判断是否登录

1.从请求头中获取token

2.通过token从redis中获取当前登录对象(object)

3.判断object是否为空,如果为空就是未登录或者登录时间过期

 /**
     * 验证是否登录
     *
     * @param request
     * @return
     */
    public boolean verifyPermissions(HttpServletRequest request) {
        String token = request.getHeader(Constant.TOKEN);
        Object o = redisUtil.get(token);
        if (o != null) {
            return true;
        }
        return false;
    }

判断是否有权限

1.从请求头中获取token

2.通过token从redis中获取当前登录对象(object)

3.通过对象查询数据库是否存在当前对象

4.获取登录对象的登录名    判断是否是(admin或者总经理)这两个账号拥有最高权限

5.判断是否被授权,(获取临时授权时设置的开始时间,结束时间,当前时间),

获取这个三个时间的时间戳,判断当前时间是否在开始时间和结束时间之间

如果开始时间和结束时间为空的话表示当前登录对象未被临时授权,会执行后面的 4,5,6,

如果有时间,但是当前时间不在这个时间段也会执行 4,5,6

如果有时间,并且当前时间在这个时间段之中,就会直接返回true

6.从请求头中获取当前接口的地址,

7.通过当前登录对象的id查询权限

8.判断当前登录对象的权限中是否包含当前接口的地址,如果包含,允许当前登录对象访问,如果不包含,则不允许当前登录人访问

 /**
     * 判断是否有权限
     *
     * @param request
     * @return
     */
    public boolean competence(HttpServletRequest request) {
        //获取当前登录对象的全部信息
        People people = peopleMapper.selectById(getUserId(request.getHeader(Constant.TOKEN)));
        //管理员拥有全部权限
        if (Constant.SUPER_ADMIN.equals(people.getUserName())) {
            return true;
        }
        //判断是否被授权
        //防止空指针
        if (people.getStartDate() != null && people.getEndDate() != null) {
            if (dateUtils.ifDate(people.getStartDate(), people.getEndDate(), new Date())) {
                return true;
            }
        }
        //从请求头中获取的地址
        String requestURI = request.getRequestURI();
        //通过角色id查询当前登陆对象的所有权限
        List<Power> list = powerMapper.selectUrl(people.getRoleid());
        ArrayList<String> stringList = new ArrayList<>();
        if (!StringUtils.isEmpty(list)) {
            list.forEach(r -> {
                stringList.add(r.getUrl());
            });
            return lsitUtils.ifcontainString(stringList, requestURI);
        }
        return false;
    }

测试

1.获取验证码

 2.登录获取token

(eyJhbGciOiJIUzI1NiJ9eyJqdGkiOiIyMDFlNmY0MS1jM2NhLTRmODItYjAxNC01NWY3ZTU5ZmNkMzgiLCJpYXQiOjE2NTIwNzE1MTMsInN1YiI6InRoayIsImlzcyI6InN0YWZmIiwiZXhwIjoxNjUyMDczMzEzfQunBHUktwyuKpT6D0NDObrPmYGjQ_yU8-lNJ0NbAwHMI)

 3.查询全部用户

总结:

避坑问题:

       在拦截器中@autowired注入工具类,或者其他service,mapper会导致空指针异常

 解决方案:

原因:

因为拦截器是在spring创建controller之前运行的,这时候这些controller,service,实体类等等这些东西spring并没有去创建,所以会注入失败,并且报空指针异常

解决方法

 将这个拦截器类也交给spring来进行管理

1.写一个@bean 来创建拦截器类

 2.在addInterceptors 方法引用中调用这个bean

3.修改后的代码

package com.thk.Interceptor;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 拦截器的属性配置
 *
 */
@Configuration
public class InterceptorConfiguration implements WebMvcConfigurer {

    /**
     * 把Interceptor这个实现类交给spring进行管理-------避坑!!!
     * @return
     */
    @Bean
    Interceptor getAdminInterceptor(){
        return new Interceptor();
    }


    /**
     * 重写addCorsMappings()解决跨域问题
     * 配置:允许http请求进行跨域访问
     *
     * @param registry
     * @Author 有梦想的肥宅
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        //指哪些接口URL需要增加跨域设置
        registry.addMapping("/**")
                //.allowedOrigins("*")//指的是前端哪些域名被允许跨域
                .allowedOriginPatterns("*")
                //需要带cookie等凭证时,设置为true,就会把cookie的相关信息带上
                .allowCredentials(true)
                //指的是允许哪些方法
                .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
                //cookie的失效时间,单位为秒(s),若设置为-1,则关闭浏览器就失效
                .maxAge(3600);
    }
 
    /**
     * 重写addInterceptors()实现拦截器
     * 配置:要拦截的路径以及不拦截的路径
     *
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //注册Interceptor拦截器(Interceptor这个类是我们自己写的拦截器类)
        InterceptorRegistration registration = registry.addInterceptor(getAdminInterceptor());
        //addPathPatterns()方法添加需要拦截的路径
        //所有路径都被拦截
        registration.addPathPatterns("/**");
        //excludePathPatterns()方法添加不拦截的路径
        //添加不拦截路径
        registration.excludePathPatterns(
                //登录
                "/login",
                //退出登录
                "/loginOut",
                //获取验证码
                "/getCode",
                //发送短信
                "/sendshortMessage",
                //重置账号
                "/unsealaccount",
                //文件上传
                "/uploadImg",
                //html静态资源
                "/**/*.html",
                //js静态资源
                "/**/*.js",
                //css静态资源
                "/**/*.css"
        );
    }
}

4.问题解决

  • 11
    点赞
  • 75
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot中,拦截器(Interceptor)是一种用于拦截和处理请求的组件。Spring Boot拦截器使用了SpringMVC技术。拦截器主要用于对请求进行预处理和后处理操作,例如验证用户权限、记录日志、跳转页面等。 与过滤器(Filter)相比,拦截器有以下区别: 1. 归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术。 2. 内容不同:Filter对所有访问进行增强,而Interceptor仅针对SpringMVC的访问进行增强。 在Spring Boot中配置拦截器需要通过创建一个配置类并实现WebMvcConfigurer接口来完成。在配置类中,可以使用addInterceptors方法添加拦截器,并通过addPathPatterns和excludePathPatterns方法来指定需要拦截和放行的请求路径。 例如,可以在配置类的addInterceptors方法中添加一个LoginInterceptor拦截器,并使用addPathPatterns("/**")来拦截所有请求,同时使用excludePathPatterns方法来放行某些请求路径,如"/login"。 代码示例: ```java @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) .addPathPatterns("/**") .excludePathPatterns("/login", "/", "/retolo", "/static/**"); } } ``` 另外,可以创建多个拦截器,并在addInterceptors方法中按照顺序添加,每个拦截器可以针对不同的请求路径进行配置。 请注意,以上代码中的LoginInterceptor是一个自定义的拦截器类,需要根据实际需求进行编写和配置。 希望以上信息能够对你有所帮助。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Springboot——拦截器](https://blog.csdn.net/weixin_51351637/article/details/128058053)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* [Springboot实现拦截器功能](https://blog.csdn.net/weixin_52875557/article/details/123793361)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值