zoukankan      html  css  js  c++  java
  • SpringBoot 使用拦截器作为权限控制

    SpringBoot 使用拦截器作为权限控制

    为什么不用Spring Security?因为Spring Security是基于filter的,而filter是依赖于servlet容器的(如tomcat)。我想做一个解耦的权限控制器,尽量摆脱servlet容器。

    什么是Spring拦截器

    Spring拦截器是基于AOP思想对HTTP资源进行拦截控制的一种手段

    为什么是HTTP资源

    Spring拦截器拦截的不仅仅是Controller中接口,理论上可以对任意通过
    HTTP访问的资源进行拦截,包括REST接口,HTML页面(包括模板),甚至是JS、CSS、图片等。
    只要是通过HTTP访问的资源都可以拦截。

    Spring拦截器可以做什么

    我们既然可以用拦截器拦截HTTP资源,那我们就可以在拦截我们需要拦截的资源时写一些逻辑,用来
    判断是否可以访问对应资源,类似关卡一样,如果访问者拥有能够访问资源的能力就放行(手令)。这样我们
    可以通过拦截器做到权限控制。并且多个拦截器对同一资源拦截时是串行的,类似与多道关卡。有了足够的权力就可以过五关斩六将了。

    如何实现

    首先拦截器是属于web这块的,那我们需要引入springboot web模块,具体版本在parent中

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    

    然后我们在config目录下新建interceptor目录,用来放拦截器

    • 我们新建两个拦截器,一个用来登陆拦截,一个用来进行管理员拦截。
    • 登陆拦截不必多说,就是判断除登陆请求外所有请求是否登陆过,没有我们就截断请求,然会返回失败状态
    • 管理员拦截,拦截的是管理员才能访问的资源,比如用户管理/权限管理等,它是登陆拦截放行后才能进行的,
      就像关卡是一关一关的。登陆验证后进入管理员验证,判断该登陆用户是否具有管理员权限,若拥有则放行,否则拦截并返回失败状态
    • 拦截器的核心是实现 org.springframework.web.servlet.HandlerInterceptor 接口,验证逻辑一般写在 preHandle 方法中,在请求资源前
    • 我的验证逻辑比较简单,登陆验证就是从session中取出用户信息,判断是否存在,用户信息是登陆成功时放入session中的,大家也可以使用JWT验证
    • 管理员验证也是从session中取出管理员信息,判断是否是管理员,管理员信息是登陆成功时将是否是管理员的信息放入session中的,大家也可以使用JWT验证

    登陆拦截器

    package com.example.interceptor_demo.config.interceptor;
    
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    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;
    import javax.servlet.http.HttpSession;
    import java.io.PrintWriter;
    import java.util.HashMap;
    import java.util.Map;
    /**
     * 拦截器,登录检查
     */
    @Component
    public class LoginInterceptor implements HandlerInterceptor {
    
        @Autowired
        private HttpSession session;
    
        @Autowired
        private ObjectMapper objectMapper;
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            Object user = session.getAttribute("sessionUser");
            if (sessionUser!=null){
                return true;
            }else {
                Map<String,Object> notLogin = new HashMap<>();
                notLogin.put("msg","not login");
                notLogin.put("code",403);
                notLogin.put("data",null);
                try(PrintWriter printWriter = response.getWriter()){
                    printWriter.print(objectMapper.writeValueAsString(notLogin));
                }catch (Exception e){
                    e.printStackTrace();
                }
                return false;
            }
        }
    
    
        @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 {
        }
    
    }
    

    管理员拦截器

    package com.example.interceptor_demo.config.interceptor;
    
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    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;
    import javax.servlet.http.HttpSession;
    import java.io.PrintWriter;
    import java.util.HashMap;
    import java.util.Map;
    /**
     * 拦截器,管理员验证
     */
    @Component
    public class AdminInterceptor implements HandlerInterceptor {
    
        @Autowired
        private HttpSession session;
    
        @Autowired
        private ObjectMapper objectMapper;
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            Boolean isAdmin = (Boolean)session.getAttribute("sessionAdmin");
            if (isAdmin!=null && isAdmin){
                return true;
            }else {
                Map<String,Object> notLogin = new HashMap<>();
                notLogin.put("msg","no power");
                notLogin.put("code",403);
                notLogin.put("data",null);
                try(PrintWriter printWriter = response.getWriter()){
                    printWriter.print(objectMapper.writeValueAsString(notLogin));
                }catch (Exception e){
                    e.printStackTrace();
                }
                return false;
            }
        }
    
    
        @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 {
        }
    
    }
    

    最后我们在config目录下新建WebMvcConfig类,用来注册拦截器

    • 拦截器注册类的核心是实现 org.springframework.web.servlet.config.annotation.WebMvcConfigurer 接口
    • 实现 addInterceptors 方法,参数 registry 对象可用来注册拦截器
    • registry.addInterceptor() 方法用来添加拦截器
    • .addPathPatterns() 方法是为该拦截器添加拦截资源路径
    • .excludePathPatterns() 方法是为该拦截器添加要放行的资源路径
    • 其中 * 代表路径下任意名称,** 代表任意路径下任意名称
    package com.example.interceptor_demo.config;
    
    import com.example.interceptor_demo.config.interceptor.AdminInterceptor;
    import com.example.interceptor_demo.config.interceptor.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.WebMvcConfigurer;
    
    @Configuration
    public class WebMvcConfig implements WebMvcConfigurer {
    
        @Autowired
        private LoginInterceptor loginInterceptor;
    
        @Autowired
        private AdminInterceptor adminInterceptor;
        
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            this.loginInterceptor(registry);//登录拦截        
            this.adminInterceptor(registry);//管理员拦截
        }
    
        private void loginInterceptor(InterceptorRegistry registry){
            registry.addInterceptor(loginInterceptor)
                    .addPathPatterns("/**")
                    .excludePathPatterns(//释放登陆接口
                            "/login/**"
                    );
        }
    
        private void adminInterceptor(InterceptorRegistry registry){
            registry.addInterceptor(htmlPageInterceptor)
                    .addPathPatterns("/admin/**");//拦截管理员接口
        }
    }
    
  • 相关阅读:
    实现CA和证书申请
    1.ssh端口
    1.对称加密6和7的操作
    关于网页访问并发量,统计前十,防火墙
    双指针法
    并查集
    c++常用函数
    vector常用方法
    贪心算法
    字符串类问题
  • 原文地址:https://www.cnblogs.com/xiaogblog/p/13985146.html
Copyright © 2011-2022 走看看