Spring如何编写一个拦截器实现鉴权呢?
下文笔者讲述Spring编写拦截器实现是否登录的验证分享,如下所示
拦截器简介
拦截器(Interceptor):
相当于Servlet中的过滤器
拦截器的功能:
用于拦截用户请求并做出相应的处理
如:
拦截器可以进行权限验证、记录请求信息的日志、判断用户是否登录等
拦截器允许自定义预处理(Pre-Processing)
在其中可以选择禁止对应Handler运行
也允许自定义后处理(Post-Precessing)
Spring拦截器的实现思路
我们可以通过实现 HandlerInterceptor接口
并重写其中的核心方法,采用这种方法可编写Spring中的拦截器
=============================================================
1.preHandle方法
在HandlerMapping确定Handler对象之后
但在HandlerAdapter调用handler之前执行
在调用controller之前执行该方法
该方法返回一个布尔值
只有true的时候才继续执行对应的handler
否则不再执行对应的handler
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
2.postHandle方法
在HandlerAdapter实际调用处理程序之后
但在DispatcherServlet呈现视图之前调用
default void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
}
3.afterCompletion方法
请求处理完成后回调
即渲染视图后
将在处理程序执行的任何结果上被调用
从而允许适当的资源清理
注意事项:
只有当这个拦截器preHandle方法成功完成并返回true时才会被调用
与postHandle方法一样
该方法将以相反的顺序在链中的每个拦截器上调用
因此第一个拦截器将是最后一个被调用
default void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {}
例:
有三个拦截器
Interceptor1 、Interceptor2、和Interceptor3
在定义三个拦截器的时
我可按照这个顺序定义
而拦截器的执行顺序就是按照之前定义的顺序执行。
Interceptor1的preHandle方法 -> Interceptor2的preHandle方法
-> Interceptor3的preHandle方法 -> controller
->Interceptor3 的postHandle方法 -> Interceptor2 的postHandle方法
-> Interceptor1 的postHandle方法 -> Interceptor3 的afterCompletion方法
-> Interceptor2 的afterCompletion方法
->Interceptor1 的afterCompletion方法
例:拦截器实现鉴权
public class SecurityInterceptor implements HandlerInterceptor {
@Autowired
private JddPmsHelper jddPmsHelper;
@Value("${global.authTest}")
private String authTest;
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
//测试环境不校验权限,需预发验证
if ("true".equals(authTest)) {
return true;
}
String uri = request.getRequestURI();
if (uri.contains("static")) {
return true;
}
String pin = ServletUtils.getCommonPin();
if (StringUtils.isBlank(pin)) {
throw new NoLoginException("未登陆");
}
if (uri.equals("/")) {
return true;
}
boolean checkResult = jddPmsHelper.authCheckUrl(pin, uri);
if (!checkResult) {
throw new NoneSecurityException("您没有权限访问,请联系管理员,对您的erp账号进行配置");
}
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 {
}
}
拦截器注册
/**
* 拦截器注册 WebConfig
*
*/
@Configuration
@Slf4j
public class WebConfig implements WebMvcConfigurer {
/**
* 登录/权限拦截器
*/
@Resource
private CombinedLoginInterceptor combinedLoginInterceptor;
/**
* 控制层切面处理
* ControllerExceptionHandler
*/
@Resource
private ControllerExceptionResolver controllerExceptionResolver;
/**
*
*/
private static final String MATCH_ALL = "/**";
/**
* 免验证
*/
private static final String APP_EXCLUDE = "/common/info";
/**
* 异常页
*/
private static final String ERROR_URL = "/error";
/**
* 无需权限验证的URI集合
*/
private static final String[] PC_WHITE_list = {APP_EXCLUDE, ERROR_URL};
@Override
public void addInterceptors(InterceptorRegistry registry) {
//PC端登录拦截,必须添加
registry.addInterceptor(combinedLoginInterceptor).addPathPatterns(MATCH_ALL)
.excludePathPatterns(PC_WHITE_LIST).order(1);
}
@Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
resolvers.add(controllerExceptionResolver);
}
}
或 使用xml注册
<!-- 单点登录拦截器配置-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.xxx.intercepter.SecurityInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。


