1. 定义拦截器 LoginInterceptor

LoginInterceptor.java是整个登录认证模块中的核心类之一,它实现了HandlerInterceptor类,由它来拦截并过滤到来的每一个请求;它的三个方法能分别作用于每个请求的不同生命周期,你可以根据自己的需要来加入相应的处理逻辑

package com.demo.common.interceptor;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map; /**
* @ProjectName: demo
* @Package: com.demo.common.interceptor
* @ClassName: LoginInterceptor
* @Description: 登录请求拦截器
* @Author:
* @Date:
* @Version: 1.0
*/
@Slf4j
public class LoginInterceptor implements HandlerInterceptor { /**
* 在请求被处理之前调用
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String requestMethod = request.getMethod();
if (requestMethod.contains("OPTIONS") || requestMethod.contains("options")) {
return true;
} //token 校验
String token = request.getHeader("token");
if (StringUtil.isEmpty(token)) {
token = request.getHeader("token-inc");
} //获取请求页面id
String pageId = "";
Map<String, String[]> paramMap = request.getParameterMap();
if (CollectionUtils.isNotEmpty(paramMap)) {
if (paramMap.containsKey("page_id")) {
pageId = paramMap.get("page_id")[];
}
} //验证token是否有效
boolean checkToken = this.checkToken(token, pageId);
if (!checkToken) {
//未登录就跳转到登录页面
//response.sendRedirect(LOGIN_HOST + "login");
Result<String> resultObject = Result.fail("", "登录超时,请刷新页面重新登录");
PrintWriter writer = response.getWriter();
writer.write(JSON.toJSONString(resultObject));
writer.flush();
writer.close();
return false;
} //参数日志打印
if (handler instanceof HandlerMethod) {
this.saveRequestLog(request);
}
return true;
} /**
* 在请求被处理后,视图渲染之前调用
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
//Collection<String> headerNames = response.getHeaderNames();
//log.info("[postHandle]{}", JsonUtils.toJson(headerNames));
} /**
* 在整个请求结束后调用
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
UserInfoHolder.removeUserInfo();
} /**
* 请求校验token 塞入ThreadLocal
*
* @param token
* @return
*/
private boolean checkToken(String token, String pageId) {
//不需要验证,直接通过,使用于直接请求接口(测试用)
if ("false".equals(ENABLE_TOKEN) || NOT_VAILE_TOKEN.equals(token)) {
return true;
} if (StringUtil.isEmpty(token)) {
return false;
} //请求获取登录用户信息及权限
HttpBO<UserInfoBO> httpBO = this.httpUserInfo(token, pageId); if (httpBO == null || httpBO.getCode() == null || httpBO.getCode() != || httpBO.getData() == null) {
return false;
} this.saveLoginContext(httpBO.getData()); return true;
} private HttpBO<UserInfoBO> httpUserInfo(String token, String pageId) {
HttpBO<UserInfoBO> httpBO = new HttpBO<>();
try {
LoginQuery loginQuery = new LoginQuery();
loginQuery.setCookieStr(token);
loginQuery.setPageId(pageId);
String url = API_HOST + USER_URL;
String jsonUserInfoBo = JSON.toJSONString(loginQuery);
log.info("发送请求获取权限参数信息 param:{},url:{}", jsonUserInfoBo, url);
String response = HttpClientPostUtil.sendPostRequest(url, jsonUserInfoBo);
log.info("发送请求获取权限返回信息 response={}", response);
Type type = new TypeReference<HttpBO<UserInfoBO>>() {
}.getType();
httpBO = JSON.parseObject(response, type);
//httpBO = JSON.parseObject(response, new HttpBO<UserInfoBO>().getClass());
log.info("发送请求获取权限信息 封装 httpBO:{}", JSON.toJSONString(httpBO));
} catch (Exception ex) {
log.error("发送请求获取权限失败 error:{}", ex.getMessage());
}
return httpBO;
} private void saveLoginContext(UserInfoBO userInfoBO) {
//List<ButtonBO> buttonBOList = userInfoBO.getUserBtns();
//if (CollectionUtils.isEmpty(buttonBOList)) {
// List<String> code = buttonBOList.stream().map(ButtonBO::getBtnCode).collect(Collectors.toList());
//} UserInfoHolder.setUserInfo(userInfoBO);
} private void saveRequestLog(HttpServletRequest request) throws Exception {
StringBuilder builder = new StringBuilder();
builder.append("请求入口 ");
builder.append("PATH => ");
builder.append(request.getRequestURI());
builder.append(",METHOD => ");
builder.append(request.getMethod());
builder.append(",PARAM => ");
Map<String, String[]> paramMap = request.getParameterMap();
if (CollectionUtils.isNotEmpty(paramMap)) {
builder.append(JSON.toJSONString(paramMap));
builder.append(",page_id => ");
if (paramMap.containsKey("page_id")) {
builder.append(paramMap.get("page_id")[]);
}
log.info(builder.toString());
return;
}
if (request instanceof MultipartHttpServletRequest) {
log.info(builder.toString());
return;
}
//由于request.getReader流只能操作一次,这里用过一次后,在Control中获取RequestBody中参数就获取不到,所以这里要先注释掉,后续解决
// BufferedReader reader = request.getReader();
// String body = this.read(reader);
// if (StringUtil.isNotEmpty(body)) {
// body = body.replace("\n", "");
// }
// builder.append(body);
log.info(builder.toString());
} private String read(Reader reader) throws IOException {
StringWriter writer = new StringWriter();
try {
this.write(reader, writer, * );
return writer.getBuffer().toString();
} finally {
writer.close();
}
} private long write(Reader reader, Writer writer, int bufferSize) throws IOException {
int read;
long total = ;
char[] buf = new char[bufferSize];
while ((read = reader.read(buf)) != -) {
writer.write(buf, , read);
total += read;
}
return total;
} }

2. 注册拦截器配置 LoginConfiguration

LoginConfiguration.java是另一个核心类之一,它继承自WebMvcConfigurer类,负责注册并生效我们自己定义的拦截器配置;在这里要注意定义好拦截路径和排除拦截的路径;

package com.demo.common.configuration;

import com.demo.common.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.handler.MappedInterceptor; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; /**
* @ProjectName: demo
* @Package: com.demo.common.configuration
* @ClassName: LoginConfiguration
* @Description: 负责注册并生效自己定义的拦截器配置
* @Author:
* @Date:
* @Version: 1.0
*/
@Configuration
public class LoginConfiguration implements WebMvcConfigurer {
@Bean
public MappedInterceptor getMappedInterceptor() {
//注册拦截器
LoginInterceptor loginInterceptor = new LoginInterceptor();
//拦截路径 ("/**")对所有请求都拦截
String[] includePatterns = new String[]{"/**"};
//排除拦截路径
String[] excludePatterns = new String[]{"/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**",
"/api", "/api-docs", "/api-docs/**"}; //将数组转化为集合
List<String> listOldExclude = Arrays.asList(excludePatterns); //将自定义的排除拦截路径添加到集合中
List<String> listNewExclude = new ArrayList<>();
listNewExclude.add("/demoJson/getCityList.json");
listNewExclude.add("/demoJson/getStudentList.json"); //定义新集合
List<String> listExclude = new ArrayList<>();
listExclude.addAll(listOldExclude);
listExclude.addAll(listNewExclude); //将新集合转化回新数组
String[] newExcludePatterns = listExclude.toArray(new String[listExclude.size()]); return new MappedInterceptor(includePatterns, newExcludePatterns, loginInterceptor);
}
}

Spring Boot拦截器实现并和swagger集成后使用拦截器的配置问题的更多相关文章

  1. Spring Boot干货系列:(六)静态资源和拦截器处理

    Spring Boot干货系列:(六)静态资源和拦截器处理 原创 2017-04-05 嘟嘟MD 嘟爷java超神学堂 前言 本章我们来介绍下SpringBoot对静态资源的支持以及很重要的一个类We ...

  2. Spring boot中使用springfox来生成Swagger Specification小结

    Rest接口对应Swagger Specification路径获取办法: 根据location的值获取api   json描述文件 也许有同学会问,为什么搞的这么麻烦,api json描述文件不就是h ...

  3. Spring Boot 2.x基础教程:Swagger静态文档的生成

    前言 通过之前的两篇关于Swagger入门以及具体使用细节的介绍之后,我们已经能够轻松地为Spring MVC的Web项目自动构建出API文档了.如果您还不熟悉这块,可以先阅读: Spring Boo ...

  4. 解决Spring Boot 从1.x升级到 2.x 后 单点登陆(SSO)问题

    解决Spring Boot 从1.x升级到 2.x 后 单点登陆(SSO)问题   在学习Spring Cloud 时,遇到了授权服务oauth 相关内容时,总是一知半解,因此决定先把Spring S ...

  5. 【转】Spring Boot干货系列:(六)静态资源和拦截器处理

    前言 本章我们来介绍下SpringBoot对静态资源的支持以及很重要的一个类WebMvcConfigurerAdapter. 正文 前面章节我们也有简单介绍过SpringBoot中对静态资源的默认支持 ...

  6. Spring Boot 2.x基础教程:Swagger接口分类与各元素排序问题详解

    之前通过Spring Boot 2.x基础教程:使用Swagger2构建强大的API文档一文,我们学习了如何使用Swagger为Spring Boot项目自动生成API文档,有不少用户留言问了关于文档 ...

  7. Spring Boot 2.x以后static下面的静态资源被拦截

    今天创建一个新的Spring Boot项目,没注意到spring boot的版本,发现静态资源无法访问.百度一下发现好像是Spring Boot 2.0版本以后static目录不能直接访问. 接下来直 ...

  8. Spring Boot(十三)RabbitMQ安装与集成

    一.前言 RabbitMQ是一个开源的消息代理软件(面向消息的中间件),它的核心作用就是创建消息队列,异步接收和发送消息,MQ的全程是:Message Queue中文的意思是消息队列. 1.1 使用场 ...

  9. Spring Boot学习笔记(二二) - 与Mybatis集成

    Mybatis集成 Spring Boot中的JPA部分默认是使用的hibernate,而如果想使用Mybatis的话就需要自己做一些配置.使用方式有两种,第一种是Mybatis官方提供的 mybat ...

随机推荐

  1. Linux下串口操作

    一.Linux下访问串口 串口位置:/dev/tty** 在Linux系统中,串口设备是通过串口终端设备文件来访问的,也就是通过访问/dev/ttyS0./dev/ttyS1./dev/ttyS2./ ...

  2. 合并K个有序链表

    方法一:采用归并的思想将链表两两合并,再将两两合并后的链表做同样的操作直到合并为只有一个新的链表为止. 归类的时间复杂度是O(logn),合并两个链表的时间复杂度是O(n),则总的时间复杂度大概是O( ...

  3. Linux端口转发工具rinetd

    介绍:Rinetd是为在一个Unix和Linux操作系统中为重定向传输控制协议(TCP)连接的一个工具.Rinetd是单一过程的服务器,它处理任何数量的连接到在配置文件etc/rinetd中指定的地址 ...

  4. Making Huge Palindromes LightOJ - 1258

    题目链接:LightOJ - 1258 1258 - Making Huge Palindromes   PDF (English) Statistics Forum Time Limit: 1 se ...

  5. LeetCode 802. Find Eventual Safe States

    原题链接在这里:https://leetcode.com/problems/find-eventual-safe-states/ 题目: In a directed graph, we start a ...

  6. 事件类型(onchange)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. mysql ERROR 1862 (HY000): 密码超时错误解决 Your password has expired.To log in you must change it using a client that supports expired password

    工具链接可能报错,使用黑窗口链接后: 1. SET PASSWORD = PASSWORD("xinmima"); 2. flush privileges; 使用新密码链接即可.

  8. 回归模型的性能评价指标(Regression Model Performance Evaluation Metric)

    回归模型的性能评价指标(Performance Evaluation Metric)通常有: 1. 平均绝对误差(Mean Absolute Error, MAE):真实目标y与估计值y-hat之间差 ...

  9. 【后缀数组】【LuoguP4248】 [AHOI2013]差异

    题目链接 题目描述 给定一个长度为 n 的字符串 S,令 Ti 表示它从第 i 个字符开始的后缀.求 \(\sum_{1\le i <j\le n}len(T_i)+len(T_j)-2*lcp ...

  10. pip崩了, 解决 ModuleNotFoundError: No module named 'pip'.

    今天 在windows下用pip 安装数据库模块pymysql  把pip 弄崩了,直接出现下面的错误.都是红字, 再输入pip install pymysql  ,会报错ModuleNotFound ...