Spring Boot拦截器实现并和swagger集成后使用拦截器的配置问题
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集成后使用拦截器的配置问题的更多相关文章
- Spring Boot干货系列:(六)静态资源和拦截器处理
Spring Boot干货系列:(六)静态资源和拦截器处理 原创 2017-04-05 嘟嘟MD 嘟爷java超神学堂 前言 本章我们来介绍下SpringBoot对静态资源的支持以及很重要的一个类We ...
- Spring boot中使用springfox来生成Swagger Specification小结
Rest接口对应Swagger Specification路径获取办法: 根据location的值获取api json描述文件 也许有同学会问,为什么搞的这么麻烦,api json描述文件不就是h ...
- Spring Boot 2.x基础教程:Swagger静态文档的生成
前言 通过之前的两篇关于Swagger入门以及具体使用细节的介绍之后,我们已经能够轻松地为Spring MVC的Web项目自动构建出API文档了.如果您还不熟悉这块,可以先阅读: Spring Boo ...
- 解决Spring Boot 从1.x升级到 2.x 后 单点登陆(SSO)问题
解决Spring Boot 从1.x升级到 2.x 后 单点登陆(SSO)问题 在学习Spring Cloud 时,遇到了授权服务oauth 相关内容时,总是一知半解,因此决定先把Spring S ...
- 【转】Spring Boot干货系列:(六)静态资源和拦截器处理
前言 本章我们来介绍下SpringBoot对静态资源的支持以及很重要的一个类WebMvcConfigurerAdapter. 正文 前面章节我们也有简单介绍过SpringBoot中对静态资源的默认支持 ...
- Spring Boot 2.x基础教程:Swagger接口分类与各元素排序问题详解
之前通过Spring Boot 2.x基础教程:使用Swagger2构建强大的API文档一文,我们学习了如何使用Swagger为Spring Boot项目自动生成API文档,有不少用户留言问了关于文档 ...
- Spring Boot 2.x以后static下面的静态资源被拦截
今天创建一个新的Spring Boot项目,没注意到spring boot的版本,发现静态资源无法访问.百度一下发现好像是Spring Boot 2.0版本以后static目录不能直接访问. 接下来直 ...
- Spring Boot(十三)RabbitMQ安装与集成
一.前言 RabbitMQ是一个开源的消息代理软件(面向消息的中间件),它的核心作用就是创建消息队列,异步接收和发送消息,MQ的全程是:Message Queue中文的意思是消息队列. 1.1 使用场 ...
- Spring Boot学习笔记(二二) - 与Mybatis集成
Mybatis集成 Spring Boot中的JPA部分默认是使用的hibernate,而如果想使用Mybatis的话就需要自己做一些配置.使用方式有两种,第一种是Mybatis官方提供的 mybat ...
随机推荐
- LeetCode 979. Distribute Coins in Binary Tree
原题链接在这里:https://leetcode.com/problems/distribute-coins-in-binary-tree/ 题目: Given the root of a binar ...
- S1_搭建分布式OpenStack集群_03 Mysql、MQ、Memcached、ETCD安装配置
一.安装mysql(contorller)controller ~]# yum -y install mariadb mariadb-server python2-PyMySQL 配置my.cnf文件 ...
- Redis的移库操作
1.Redis默认有16个数据库,一般情况下使用0库: 2.移库操作: 将mysets移到一号库: 通过Redis查看器查看: 通过命令查看:
- 开源项目 08 IOC Autofac
using Autofac; using System; using System.Collections.Generic; using System.Linq; using System.Text; ...
- 开源项目 06 NPOI
using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using NPOI.XSSF.UserModel; using System; using S ...
- 【后缀数组】【LuoguP4051】 [JSOI2007]字符加密
题目链接 题目描述 喜欢钻研问题的JS 同学,最近又迷上了对加密方法的思考.一天,他突然想出了一种他认为是终极的加密办法:把需要加密的信息排成一圈,显然,它们有很多种不同的读法. 例如'JSOI07' ...
- mysql adddate()函数
mysql> ); +---------------------------+ | adddate() | +---------------------------+ | -- | +----- ...
- 【cf补题记录】A. Hotelier
思考之后再看题解,是与别人灵魂之间的沟通与碰撞 A. Hotelier 题意 给出长度为n的字符串,字符串由'L'.'R'以及数字0~9组成.旅馆有10间房子,L代表客人从左边入住,R代表客人从右边入 ...
- 使用深度学习的超分辨率介绍 An Introduction to Super Resolution using Deep Learning
使用深度学习的超分辨率介绍 关于使用深度学习进行超分辨率的各种组件,损失函数和度量的详细讨论. 介绍 超分辨率是从给定的低分辨率(LR)图像恢复高分辨率(HR)图像的过程.由于较小的空间分辨率(即尺寸 ...
- updateprimarykey 和updateprimaryKeySelective
updateprimarykey 会对左右的字段都进行更新,updateprimaryKeySelective 只会对不为null的字段进行更新..所以在填表的web项目需要注意这个两个方法的选择,因 ...