Spring Boot/Spring MVC 設置請求攔截器,自定義註解,實現權限管理

爲何要寫這個:
緣由簡單,就是需求來了,哈哈!!!
要求:
1.本身對外提供的接口,哪些廠商有權限訪問。
2.每一個接口限制訪問次數,天天須要重置訪問次數上限。
具體的緣由不說了,千言萬語就是安全,安全,安全。redis


開始咱們的表演
先來一遍Spring Boot
在來一遍Spring MVCspring

第一個重點:本身對外提供的接口,哪些廠商有權限訪問
1、設置攔截URL請求數據庫

/**
 * @Description: 設置攔截
 * @author: 你瞅瞅~~
 * @create: 2020-01-10 14:51
 */
public class AuthRequestInterceptor implements HandlerInterceptor {  
  
  @Autowired  
  private AuthService authService;  
  
     @Override  
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  
              // 驗證權限  
              if (handler instanceof HandlerMethod) {  
              HandlerMethod handlerMethod = (HandlerMethod) handler;  
              // AuthRequest是咱們定義在controller方法上的註解~  
              AuthRequest authRequest = handlerMethod.getMethod().getAnnotation(AuthRequest.class);  
              // AuthRequest是咱們定義在controller類上的註解~  
              if (authRequest == null) {  
              authRequest = handlerMethod.getMethod().getDeclaringClass().getAnnotation(RequiredPermission.class);  
              // 獲取請求URL  
              String requestURI = request.getRequestURI();  
              // 校驗接口URL/訪問次數  
              // redis或數據庫(加緩存) 中獲取該用戶的權限信息 並判斷是否有權限  
              List<String> authCount = authService.getAuthCount();  
              if (!authURL.contains(requestURI)) {  
                  return false;  
              }   
              // 這裏簡單寫一下,明確一點就是【接口URL --> 訪問次數】
              Long accessCount = authCount.getAccessCount();  
              if (accessCount < 0) {  
                 return false;  
              } else {  
                int count = accessCount - 1;
                authService.updateCount(count);  
              }  
           }  
          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 {  
    }
 
 }

2、使用註解的攔截器
寫這個註解的意思很明確,這樣無論在哪裏項目均可以設置統一攔截,給你們提供一個簡單的註解就完事了,若是你用了Spring boot你就知道註解是多麼省事。express

自定義一個註解 AuthRequest 類segmentfault

/**
 * @Description: 註解攔截
 * @author: 你瞅瞅~~
 * @create: 2020-01-10 14:51
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface AuthRequest {
    String value();
}

三.攔截配置文件WebAppConfig
@Configuration 這個註解,在啓動的時候在會被加載
多個攔截就設置多個相似定義方法 getInterceptor1()/getInterceptor2()緩存

/**
 * @Description:對外接口權限攔截  
 * @author: 你瞅瞅~~
 * @create: 2020-01-10 14:51
 */
@Configuration
public class WebAppConfig extends WebMvcConfigurerAdapter {  

  
  @Override  
  public void addInterceptors(InterceptorRegistry registry) {
        // 攔截@AuthRequest註解的所求請求
        // addPathPatterns 用於添加攔截規則  
        // excludePathPatterns 用戶排除攔截
        registry.addInterceptor(getInterceptor1()).addPathPatterns("/login/**");
        registry.addInterceptor(getInterceptor2()).addPathPatterns("/login2/**");  
        super.addInterceptors(registry);  
   }  
  
  
  @Bean  
  public HandlerInterceptor getInterceptor(){  
        return new authInterceptor;  
  }  
  
}

四.Controller添加攔截請求註解安全

/**
 * @Description:對外接口權限攔截  
 * @author: 你瞅瞅~~
 * @create: 2020-01-10 14:51
 */
這個註解就是攔截整個Controller全部請求,全局註解
@AuthRequest
@RequestMapping("/login")
public class AuthController {  
   
  private static final String  NO_AUTH = "接口權限";
  
  // 權限註解,至關於局部註解,AuthController.AuthRequest表示在進入攔截判斷是否有值 
  @AuthRequest(AuthController.AuthRequest) 
  @RequestMapping("/list")
  public String list() {  
      // 各類操做
      return "/login/users";  
  }  
  
  // 未註解,表示不攔截 
  @RequestMapping("/de;ete")  
  public String detail() {  
      // 各類操做
      return "/login/user";  
  }  
 
}

第二個重點:每一個接口限制訪問次數,天天須要重置訪問次數上限
簡單說明:設置定時刷新任務,在須要刷新的方法上定時刷新,這樣就能夠天天獲取重置次數,固然也可寫到redis裏,這樣的話,就能夠不用定時刷新獲取。mvc

1.Application 要加註解,也就是總開關@EnableAsync
2.在須要獲取的接口上加上@Scheduled 配置cron表達式app

/**
 * @Description: 定時任務,天天刷新請求次數   
 * @author: 你瞅瞅~~
 * @create: 2020-01-10 14:51
 */
@Scheduled(cron = "0 0 1 * * ?")  
// 天天凌晨一點刷新接口,authRequest定義一個全局變量
public void accessCountCurrentByCron() {  
        List<String> authRequest = authRequest.getAuthRequests();   if(authRequest.size !=0){
        logger.warn("我在刷新。。。");  
        result authRequest;
      }
  }  
}

爲何寫Spring mvc 由於咱們有老項目,嘿嘿
重頭再來,咱們走完了Spring boot,那來講說Spring mvc ide

在咱們SpringMVC中也可使用攔截器對用戶的請求進行攔截,
用戶能夠自定義攔截器來實現 HandlerInterceptor

主要區別就是個添個配置,Spring boot能夠用註解完事,Spring mvc須要寫在配置文件,剩下的都同樣。
1、添加簡單配置springmvc.xml

<mvc:interceptors>  
 <mvc:interceptor>  
 <mvc:mapping path\="/login/**"/>  
 <bean class\="com.interceptor.AuthInterceptor"/>  
 </mvc:interceptor>  
</mvc:interceptors>

// 這裏是爲了掃描到註釋@AuthRequest
// 啓動包掃描功能,以便註冊帶有@Controlle
<context:component-scan base-package\="com.org.須要攔截的類" use-default-filters\="false"\>  
 <context:include-filter type\="annotation" expression\="org.springframework.stereotype.Controller"/>  
 <context:include-filter type\="annotation" expression\="com.interceptor.AuthRequest"/>  
</context:component-scan>

能夠參考這篇文章,spring mvc的用法Controller寫的很詳細 :[https://segmentfault.com/a/11...]

碰見的問題【重點】
HandlerInterceptor攔截器使用中,就能碰見這個問題,

Required request body is missing OR Stream closed

繼承並實現 HttpServletRequestWrapper包裝類,有時間在補充......

相關文章
相關標籤/搜索