为什么要写这个:
原因简单,就是需求来了,哈哈!!!
要求:
1.自己对外提供的接口,哪些厂商有权限访问。
2.每个接口限制访问次数,每天需要重置访问次数上限。
具体的原因不说了,千言万语就是安全,安全,安全。
开始我们的表演
先来一遍Spring Boot
在来一遍Spring MVC
第一个重点:自己对外提供的接口,哪些厂商有权限访问
一、设置拦截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 {
}
}
二、使用注解的拦截器
写这个注解的意思很明确,这样不管在哪里项目都可以设置统一拦截,给大家提供一个简单的注解就完事了,如果你用了Spring boot你就知道注解是多么省事。
自定义一个注解 AuthRequest 类
/**
* @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("/delete")
public String detail() {
// 各种操作
return "/login/user";
}
}
第二个重点:每个接口限制访问次数,每天需要重置访问次数上限
简单说明:设置定时刷新任务,在需要刷新的方法上定时刷新,这样就可以每天获取重置次数,当然也可写到redis里,这样的话,就可以不用定时刷新获取。
1.Application 要加注解,也就是总开关@EnableAsync
2.在需要获取的接口上加上@Scheduled 配置cron表达式
/**
* @Description: 定时任务,每天刷新请求次数
* @author: 你瞅瞅~~
* @create: 2020-01-10 14:51
*/
@Scheduled(cron = "0 0 1 * * ?")
// 每天凌晨一点刷新接口,authRequest定义一个全局变量
public void accessCountCurrentByCron() {
List<String> authRequest = authRequest.getAuthRequests();
logger.warn("我在刷新。。。");
result authRequest;
}
}
}
为什么写Spring mvc 因为我们有老项目,嘿嘿
重头再来,我们走完了Spring boot,那来说说Spring mvc
在我们SpringMVC中也可以使用拦截器对用户的请求进行拦截,
用户可以自定义拦截器来实现 HandlerInterceptor
主要区别就是个添个配置,Spring boot可以用注解完事,Spring mvc需要写在配置文件,剩下的都一样。
一、添加简单配置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包装类,可参考这一篇
[https://segmentfault.com/a/11...]
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。