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. Centos7 Rsync怎么实现热备份笔记

    应用场景:备份Web服务器相关目录下的数据文件,确保指定目录下的所有文件同步. 操作系统:Centos 7 服务器两台:web服务器 172.19.242.70  备份服务器 172.19.242.7 ...

  2. test20190926 孙耀峰

    70+100+0=170.结论题自己还是要多试几组小数据.这套题还不错. ZYB建围墙 ZYB之国是特殊的六边形构造. 已知王国一共有

  3. git提交项目到已有库

    借鉴地址:https://blog.csdn.net/jerryhanjj/article/details/72777618 Git global setup git config --global ...

  4. vue 选择之单选,多选,反选,全选,反选

    1.单选 当我们用v-for渲染一组数据的时候,我们可以带上index以便区分他们我们这里利用这个index来简单地实现单选. <li v-for="(item,index) in r ...

  5. 解决bash: less: command not found

    问题描述 使用less命令查找日志时,less命令未找到: 解决办法 安装less,执行如下命令: npm install -g less

  6. 数论--扩展欧几里得exgcd

    算法思想 我们想求得一组\(x,y\)使得 \(ax+by = \gcd(a,b)\) 根据 \(\gcd(a,b) = \gcd(b,a\bmod b)\) 如果我们现在有\(x',y'\) 使得 ...

  7. c++ 去掉所有空格及换行符

    string get_string(string res){ //删除换行符 int r = res.find('\r\n'); while (r != string::npos) { if (r ! ...

  8. Redis存储Sortedset

    与set相比Sortedset多了一个数字与set中的各个元素相关联. 存储结构: 1.添加元素: 添加元素的时候元素一定不能相同,如果已存在该元素,表示插入失败返回0,成功返回1,但是不同元素的数字 ...

  9. svn项目迁移至gitlab

    关于svn项目迁移有人可能会说,新建一个git项目,把原来的代码直接扔进去提交不完了吗.恩,是的,没错.但是为了保留之前的历史提交记录,还是得做下面的步骤 首先确保本地正常安装配置好git,具体步骤不 ...

  10. 洛谷 CF894A QAQ

    目录 题目 思路 \(Code\) 题目 CF894A 思路 \(\text{DP}\) 一个数组\(\text{QAQ[4][101]}\) \(\text{QAQ[1][i]表示在i这个位置q的个 ...