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. 大数据开发之keras代码框架应用

    总体来讲keras这个深度学习框架真的很“简易”,它体现在可参考的文档写的比较详细,不像caffe,装完以后都得靠技术博客,keras有它自己的官方文档(不过是英文的),这给初学者提供了很大的学习空间 ...

  2. Linux学习笔记——管道PIPE

    管道:当从一个进程连接数据流到另一个进程时,使用术语管道(pipe).# include <unistd.h> int pipe(int filedes[2]); //创建管道 pipe( ...

  3. C#中ref和out的原理

    去年在CSDN上写的,现在把它搬过来. 一.引发问题 用了那么久的 ref 和 out ,你真的了解它们是如何使得实参与形参的值保持同步的吗? 二.研究前提 要研究这个问题,前提是要了解 C# 中方法 ...

  4. [CodeForces 663E] - Binary Table(FWT)

    题目 Codeforces 题目链接 分析 大佬博客,写的很好 本蒟蒻就不赘述了,就是一个看不出来的异或卷积 精髓在于 mask对sta的影响,显然操作后的结果为mask ^ sta AC code ...

  5. IDEA设置类注释和方法注释模板

    背景 在日常开发中,类和方法上希望有属于自己风格的注释模板,此文将记录如何设置IDEA类和方法注释模板. 注意:如果公司有统一的规范模板,请按照公司提供的规范模板去设置,这样可以统一代码注释风格.当然 ...

  6. BZOJ 5082: 弗拉格 矩阵乘法

    如果单点而不是求 sigma 的话还是比较好办的. 遇到这种前缀和相减的矩阵乘法可以增设一个 0 使得后面的能先加到前面,然后再算. 这样的话可以使的最后算出的是前缀和相加的形式. code: #in ...

  7. 原生 ajax 请求

    ajax 即 Asynchronous Javascript And XML,AJAX 不是一门的新的语言,而是对现有持术的综合利用.本质是在 HTTP 协议的基础上以异步的方式与服务器进行通信. 异 ...

  8. python学习笔记一: 《python3 input()函数》

    一.在学习之前需要先了解: 1.Python3.x 中 input() 函数接受一个标准输入数据,返回为 string 类型,即把任何输入看作str. 2.input可以用作文本输入,如用户名,密码框 ...

  9. 手把手实例对比String、StringBuilder字符串的连接效率及StringBuilder和StringBuffer线程安全的比较

    一.字符串连接的效率问题 使用String连接字符串时为什么慢? 小知识点 java中对数组进行初始化后,该数组所占的内存空间.数组长度都是不可变的. 创建一个字符串,为字符串对象分配内存空间,会耗费 ...

  10. C# linq 使用Groupby lamda 获取非重复数据

    ).GroupBy(b => b.BasicUserId).Select(a => new MyServicesListViewModel() { HeadIcon = apiUrl + ...