获取前端调用接口传递的body参数
代码实现
配置类:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebAppConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new CommonHandlerInterceptor()).addPathPatterns("
@Slf4j
public class CommonHandlerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) throws Exception {
if (isJson(request)) {
String body = new RequestWrapper(request).getBody();
log.info("【前端请求接口,传递Body参数】----》{}: ", body);
}
String servletPath = request.getServletPath();
ClTerminalLoginAsync clTerminalLoginAsync = new ClTerminalLoginAsync();
clTerminalLoginAsync.saveClTerminalLonginInfo(request);
if(StringUtils.isNotEmpty(servletPath)){
if("/login/mobile".equals(servletPath) ||
"/getToken".equals(servletPath)||
"/login/getValidateCode".equals(servletPath)
){
return true;
}
}
// 2. 获取token
String accessToken = request.getHeader(TokenConstants.TOKEN_REQUEST_KEY);
// 3. 校验token是否为空
if (StringUtils.isNotEmpty(accessToken)) {
// 3.1 校验token格式
if (accessToken.contains(TokenConstants.TOKEN_REQUEST_HEAD)) {
accessToken = accessToken.replace(TokenConstants.TOKEN_REQUEST_HEAD, "");
}
// 3.2 校验token是否有效
boolean verify = TokenUtils.verify(accessToken);
if (verify) {
return true;
} else {
throw new TokenbaseException(HttpStatusEnums.CLI_TOOKEN_ERR_GENERAL_TIPS, "token 失效");
}
} else {
throw new TokenbaseException(HttpStatusEnums.CLI_TOOKEN_ERR_GENERAL_TIPS, "token 不可为空!");
}
}
private boolean isJson(HttpServletRequest request) {
if (request.getContentType() != null) {
return request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE) ||
request.getContentType().equals(MediaType.APPLICATION_JSON_UTF8_VALUE);
}
return false;
}
}
自定义拦截器:
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@Component
@WebFilter(filterName = "HttpServletRequestFilter", urlPatterns = "/")
@Order(10000)
public class HttpServletRequestFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
ServletRequest requestWrapper = null;
if(servletRequest instanceof HttpServletRequest) {
requestWrapper = new RequestWrapper((HttpServletRequest) servletRequest);
}
//获取请求中的流如何,将取出来的字符串,再次转换成流,然后把它放入到新request对象中
// 在chain.doFiler方法中传递新的request对象
if(null == requestWrapper) {
filterChain.doFilter(servletRequest, servletResponse);
} else {
filterChain.doFilter(requestWrapper, servletResponse);
}
}
@Override
public void destroy() {
}
}
解决: request.getInputStream()只能读取一次的问题,目标: 流可重复读–核心类
import lombok.extern.slf4j.Slf4j;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.Charset;
@Slf4j
public class RequestWrapper extends HttpServletRequestWrapper {
private String mBody;
public RequestWrapper(HttpServletRequest request) {
super(request);
// 将body数据存储起来
mBody = getBody(request);
}
private String getBody(HttpServletRequest request) {
try {
ServletInputStream inputStream = request.getInputStream();
return getBodyString(inputStream);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public String getBody() {
return mBody;
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public ServletInputStream getInputStream() throws IOException {
// 创建字节数组输入流
final ByteArrayInputStream bais = new ByteArrayInputStream(mBody.getBytes(Charset.defaultCharset()));
return new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return bais.read();
}
};
}
public static String getBodyString( ServletInputStream inputStream) {
StringBuilder sb = new StringBuilder();
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
}
token工具类
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.cmsweety.vo.LoginVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Component
public class TokenUtils {
private static RedisTemplate redisTemplate;
@Autowired
public void setRedisTemplate(RedisTemplate redisTemplate){
TokenUtils.redisTemplate = redisTemplate;
}
public static String sign(LoginVO loginVO) {
try {
// token过期时间
Date date = new Date(System.currentTimeMillis() + TokenConstants.REDIS_TOKEN_EXPIRATION_TIME);
// 私钥及加密算法
Algorithm algorithm = Algorithm.HMAC256(TokenConstants.TOKEN_SECRET);
// 设置头信息:加密类型、加密算法
Map header = new HashMap<>();
header.put("type", TokenConstants.TOKEN_ENCRYPTION_TYPE);
header.put("algorithm", TokenConstants.TOKEN_ENCRYPTION_ALGORITHM);
String sign = JWT.create()
.withHeader(header)
.withClaim("userId", loginVO.getUserId())
.withExpiresAt(date)
.sign(algorithm);
redisTemplate.boundValueOps(TokenConstants.REDIS_TOKEN_KEY+loginVO.getUserId())
.set(sign,TokenConstants.REDIS_TOKEN_EXPIRATION_TIME, TimeUnit.MINUTES);
return sign;
} catch (Exception e) {
return null;
}
}
public static boolean verify(String token) {
try {
Boolean hasKey = redisTemplate.hasKey(TokenConstants.REDIS_TOKEN_KEY+getUsername(token));
if (hasKey) {
// 重新设置过期时间
redisTemplate.expire(TokenConstants.REDIS_TOKEN_KEY+getUsername(token),
TokenConstants.EXPIRATION_TIME, TimeUnit.MINUTES);
return true;
} else {
return false;
}
} catch (Exception e) {
return false;
}
}
public static Long getUsername(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
Long userId = jwt.getClaim("userId").asLong();
return userId;
} catch (Exception e) {
return null;
}
}
}
获取请求头参数
import cn.hutool.core.util.ObjectUtil;
import com.xxxxx.common.HttpStatusEnums;
import com.xxxx.exception.RequestIllegalArgumentException;
import com.xxxxxx.token.TokenUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.http.HttpServletRequest;
@Slf4j
public class ClTerminalLoginAsync {
public void saveClTerminalLonginInfo(HttpServletRequest request){
String ip = getIp(request);
String servletPath = request.getServletPath();
String cmtoken = request.getHeader("Cmtoken");
String imei = request.getHeader("imei");
String terminalType = request.getHeader("terminalType");
String appVersion = request.getHeader("appVersion");
String dataSource = request.getHeader("dataSource");
String deviceName = request.getHeader("deviceName");
String terminalVersion= request.getHeader("terminalVersion");
if( StringUtils.isEmpty(ip) ||StringUtils.isEmpty(servletPath)||
StringUtils.isEmpty(imei) || StringUtils.isEmpty(terminalType) ||
StringUtils.isEmpty(appVersion)||StringUtils.isEmpty(dataSource)||
StringUtils.isEmpty(deviceName) ||StringUtils.isEmpty(terminalVersion)
){
throw new RequestIllegalArgumentException(HttpStatusEnums.CLI_ERR_EMPTY_PARAM);
}
if(StringUtils.isNotEmpty(terminalType)){
switch (terminalType){
case "0":
terminalType="ios";
break;
case "1":
terminalType="android";
break;
case "2":
terminalType="H5";
break;
default:
terminalType="没有获取到";
}
}
Long username =0L;
if(ObjectUtil.isNotEmpty(cmtoken)){
username = TokenUtils.getUsername(cmtoken);
}
log.info("【前端请求】---》【ip】-->{}---->" +
"[接口名称]---》{}-->[终端类型]--->{}----" +
"[接口版本号] ---->{}----[userID]----》{}----" +
"[imei]------>{}---------" +
"[推广渠道]----->{}--------" +
"[设备名称]----->{}--------" +
"[终端版本号]--->{}--------",
ip,servletPath,terminalType,appVersion,
username==0?"【获取短信、刷新token、登录接口等不需要传递token】":username,
imei,dataSource,deviceName,terminalVersion);
}
private String getIp(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (ip != null) {
if (!ip.isEmpty() && !"unKnown".equalsIgnoreCase(ip)) {
int index = ip.indexOf(",");
if (index != -1) {
return ip.substring(0, index);
} else {
return ip;
}
}
}
ip = request.getHeader("X-Real-IP");
if (ip != null) {
if (!ip.isEmpty() && !"unKnown".equalsIgnoreCase(ip)) {
return ip;
}
}
ip = request.getHeader("Proxy-Client-IP");
if (ip != null) {
if (!ip.isEmpty() && !"unKnown".equalsIgnoreCase(ip)) {
return ip;
}
}
ip = request.getHeader("WL-Proxy-Client-IP");
if (ip != null) {
if (!ip.isEmpty() && !"unKnown".equalsIgnoreCase(ip)) {
return ip;
}
}
ip = request.getRemoteAddr();
return ip.equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip;
}
}
测试



