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>
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。