登录会话拦截优化

This commit is contained in:
暮光:城中城
2021-11-23 22:30:25 +08:00
parent 80d525b735
commit b32c9a8f9e
12 changed files with 152 additions and 348 deletions

10
pom.xml
View File

@@ -145,16 +145,6 @@
<artifactId>freemarker</artifactId> <artifactId>freemarker</artifactId>
<version>2.3.28</version> <version>2.3.28</version>
</dependency> </dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.9.4</version>
</dependency>
<dependency> <dependency>
<groupId>javax.servlet</groupId> <groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId> <artifactId>servlet-api</artifactId>

View File

@@ -1,6 +1,7 @@
package com.zyplayer.doc.core.json; package com.zyplayer.doc.core.json;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.serializer.SerializeConfig; import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SimpleDateFormatSerializer; import com.alibaba.fastjson.serializer.SimpleDateFormatSerializer;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -20,9 +21,11 @@ import java.util.Objects;
*/ */
public class DocResponseJson<T> implements ResponseJson<T> { public class DocResponseJson<T> implements ResponseJson<T> {
private static SerializeConfig mapping = new SerializeConfig(); private static SerializeConfig mapping = new SerializeConfig();
static { static {
mapping.put(Date.class, new SimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss")); mapping.put(Date.class, new SimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss"));
} }
@ApiModelProperty(value = "状态码") @ApiModelProperty(value = "状态码")
private Integer errCode; private Integer errCode;
@ApiModelProperty(value = "返回值说明") @ApiModelProperty(value = "返回值说明")
@@ -37,46 +40,46 @@ public class DocResponseJson<T> implements ResponseJson<T> {
private Integer pageSize; private Integer pageSize;
@ApiModelProperty(value = "总页数") @ApiModelProperty(value = "总页数")
private Integer totalPage; private Integer totalPage;
public DocResponseJson() { public DocResponseJson() {
this.errCode = 200; this.errCode = 200;
} }
public DocResponseJson(Object data) { public DocResponseJson(Object data) {
this.setData(data); this.setData(data);
this.errCode = 200; this.errCode = 200;
} }
public DocResponseJson(int errCode, String errMsg) { public DocResponseJson(int errCode, String errMsg) {
super(); super();
this.errCode = errCode; this.errCode = errCode;
this.errMsg = errMsg; this.errMsg = errMsg;
} }
public DocResponseJson(int errCode, String errMsg, Object data) { public DocResponseJson(int errCode, String errMsg, Object data) {
super(); super();
this.setData(data); this.setData(data);
this.errCode = errCode; this.errCode = errCode;
this.errMsg = errMsg; this.errMsg = errMsg;
} }
public DocResponseJson(Integer errCode) { public DocResponseJson(Integer errCode) {
super(); super();
this.errCode = errCode; this.errCode = errCode;
} }
public Integer getErrCode() { public Integer getErrCode() {
return errCode; return errCode;
} }
public void setErrCode(Integer errCode) { public void setErrCode(Integer errCode) {
this.errCode = errCode; this.errCode = errCode;
} }
public String getErrMsg() { public String getErrMsg() {
return errMsg; return errMsg;
} }
public void setErrMsg(String errMsg) { public void setErrMsg(String errMsg) {
this.errMsg = errMsg; this.errMsg = errMsg;
} }
@@ -138,13 +141,13 @@ public class DocResponseJson<T> implements ResponseJson<T> {
} }
} }
} }
/** /**
* 提示语 * 提示语
* *
* @return
* @author 暮光:城中城 * @author 暮光:城中城
* @since 2018年8月7日 * @since 2018年8月7日
* @return
*/ */
public static <T> DocResponseJson<T> warn(String errMsg) { public static <T> DocResponseJson<T> warn(String errMsg) {
return new DocResponseJson<T>(300, errMsg); return new DocResponseJson<T>(300, errMsg);
@@ -153,9 +156,9 @@ public class DocResponseJson<T> implements ResponseJson<T> {
/** /**
* 错误 * 错误
* *
* @return
* @author 暮光:城中城 * @author 暮光:城中城
* @since 2018年8月7日 * @since 2018年8月7日
* @return
*/ */
public static <T> DocResponseJson<T> error(String errMsg) { public static <T> DocResponseJson<T> error(String errMsg) {
return new DocResponseJson<T>(500, errMsg); return new DocResponseJson<T>(500, errMsg);
@@ -164,31 +167,31 @@ public class DocResponseJson<T> implements ResponseJson<T> {
/** /**
* 失败 * 失败
* *
* @return
* @author 暮光:城中城 * @author 暮光:城中城
* @since 2018年8月7日 * @since 2018年8月7日
* @return
*/ */
public static <T> DocResponseJson<T> failure(int errCode, String errMsg) { public static <T> DocResponseJson<T> failure(int errCode, String errMsg) {
return new DocResponseJson<T>(errCode, errMsg); return new DocResponseJson<T>(errCode, errMsg);
} }
/** /**
* 成功的返回方法 * 成功的返回方法
* *
* @return
* @author 暮光:城中城 * @author 暮光:城中城
* @since 2018年8月7日 * @since 2018年8月7日
* @return
*/ */
public static <T> DocResponseJson<T> ok() { public static <T> DocResponseJson<T> ok() {
return new DocResponseJson<>(); return new DocResponseJson<>();
} }
/** /**
* 成功的返回方法 * 成功的返回方法
* *
* @return
* @author 暮光:城中城 * @author 暮光:城中城
* @since 2018年8月7日 * @since 2018年8月7日
* @return
*/ */
public static <T> DocResponseJson<T> ok(Object data) { public static <T> DocResponseJson<T> ok(Object data) {
if (data == null) { if (data == null) {
@@ -198,7 +201,7 @@ public class DocResponseJson<T> implements ResponseJson<T> {
responseJson.setData(data); responseJson.setData(data);
return responseJson; return responseJson;
} }
public String toJson() { public String toJson() {
return JSON.toJSONString(this, mapping); return JSON.toJSONString(this, mapping);
} }
@@ -215,6 +218,7 @@ public class DocResponseJson<T> implements ResponseJson<T> {
} }
} }
@JSONField(serialize = false)
public boolean isOk() { public boolean isOk() {
return Objects.equals(this.errCode, 200); return Objects.equals(this.errCode, 200);
} }
@@ -223,5 +227,5 @@ public class DocResponseJson<T> implements ResponseJson<T> {
public String toString() { public String toString() {
return "DefaultResponseJson [errCode=" + errCode + ", errMsg=" + errMsg + ", data=" + data + "]"; return "DefaultResponseJson [errCode=" + errCode + ", errMsg=" + errMsg + ", data=" + data + "]";
} }
} }

View File

@@ -99,14 +99,6 @@
<groupId>org.freemarker</groupId> <groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId> <artifactId>freemarker</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -1,73 +0,0 @@
package com.zyplayer.doc.data.aspect;
import com.google.common.collect.Maps;
import com.zyplayer.doc.core.annotation.AuthMan;
import com.zyplayer.doc.core.json.DocResponseJson;
import com.zyplayer.doc.core.json.HttpConst;
import com.zyplayer.doc.core.json.ResponseJson;
import com.zyplayer.doc.core.util.ThreadLocalUtil;
import com.zyplayer.doc.data.config.security.DocUserDetails;
import com.zyplayer.doc.data.config.security.DocUserUtil;
import com.zyplayer.doc.data.utils.BeanUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.Map;
@Aspect
@Component
public class AuthAspect {
@Around(value = "@annotation(com.zyplayer.doc.core.annotation.AuthMan) || @within(com.zyplayer.doc.core.annotation.AuthMan)")
public Object authController(ProceedingJoinPoint pjp) throws Throwable {
AuthMan authMan = BeanUtil.getAnnotation(pjp, AuthMan.class);
ResponseBody responseBody = BeanUtil.getAnnotation(pjp, ResponseBody.class);
RestController restController = BeanUtil.getAnnotation(pjp, RestController.class);
boolean isResponseBody = (restController != null || responseBody != null);
Class<?> returnType = ((MethodSignature) pjp.getSignature()).getMethod().getReturnType();
DocUserDetails currentUser = DocUserUtil.getCurrentUser();
if (currentUser == null) {
String reason = "你访问的内容需要登录,请登录后再试";
if (isResponseBody) {
return DocResponseJson.failure(HttpConst.TOKEN_TIMEOUT, reason);
} else if (returnType.isAssignableFrom(ModelAndView.class)) {
HttpServletRequest request = ThreadLocalUtil.getHttpServletRequest();
StringBuffer requestURL = request.getRequestURL();
String requestURLStr = URLEncoder.encode(requestURL.toString(), "utf-8");
return new ModelAndView("redirect:./#/user/login?redirect=" + requestURLStr);
} else if (returnType.isAssignableFrom(Map.class)) {
return Maps.newHashMap();
}
}
// 判断权限是否足够
boolean haveAuth = DocUserUtil.haveAuth(authMan.value());
if (haveAuth) {
return pjp.proceed();
}
String reasonStr = "没有操作权限,请联系管理员";
if (isResponseBody) {
Method method = ((MethodSignature) pjp.getSignature()).getMethod();
if (method.getReturnType().equals(ResponseJson.class)) {
return DocResponseJson.warn(reasonStr);
} else {
try {
return Class.forName(method.getReturnType().getName()).newInstance();
} catch (Exception e) {
return null;
}
}
} else {
return authMan.authUrl();
}
}
}

View File

@@ -1,91 +0,0 @@
package com.zyplayer.doc.data.config;
import com.zyplayer.doc.core.json.HttpConst;
import com.zyplayer.doc.data.config.security.DocUserUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 登录和跨域拦截器
* @author 暮光:城中城
* @since 2019年05月25日
*/
@Component
public class DocLoginOriginInterceptor implements HandlerInterceptor {
@Value("${zyplayer.doc.manage.originDomainRegex:}")
private String originDomainRegex;
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object arg2, Exception arg3) {
// 清理用户信息
DocUserUtil.clean();
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object haddler, ModelAndView modelAndView) {
}
/**
* 记录请求信息
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) {
// 指定域名可跨域访问
if (StringUtils.isNotBlank(originDomainRegex)) {
String origin = request.getHeader("Origin");
if (StringUtils.isNotBlank(origin) && origin.toLowerCase().matches(originDomainRegex)) {
response.setHeader("Access-Control-Allow-Origin", origin); // 允许访问的域
response.setHeader("Access-Control-Allow-Methods", "HEAD,GET,POST,PUT,DELETE");// 允许GET、POST的外域请求
response.setHeader("Access-Control-Allow-Credentials", "true"); // 允许请求带cookie到服务器
response.setContentType("application/json; charset=utf-8"); // 设定JSON格式标准输出、及编码
}
}
// 清理用户信息
DocUserUtil.clean();
// 设置token
String accessToken = getCookieValueByRequest(request, HttpConst.ACCESS_TOKEN);
DocUserUtil.setAccessToken(accessToken);
return true;
}
/**
* 获取cookie
*
* @param request
* @param name
* @return
*/
public static Cookie getCookieByRequest(HttpServletRequest request, String name) {
if (StringUtils.isEmpty(name)) {
return null;
}
Cookie[] cookies = request.getCookies();
for (int i = 0; (cookies != null) && (i < cookies.length); i++) {
Cookie cookie = cookies[i];
if (name.equals(cookie.getName())) {
return cookie;
}
}
return null;
}
/**
* 获取cookie值
*
* @param request
* @param name
* @return
*/
public static String getCookieValueByRequest(HttpServletRequest request, String name) {
Cookie cookie = getCookieByRequest(request, name);
return cookie == null ? null : cookie.getValue();
}
}

View File

@@ -1,33 +0,0 @@
package com.zyplayer.doc.data.utils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.MethodSignature;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class BeanUtil {
@SuppressWarnings({"unchecked"})
public static <T extends Annotation> T getAnnotation(JoinPoint pjp, Class<T> t) throws Exception {
Method method = ((MethodSignature) pjp.getSignature()).getMethod();
T annotation = method.getAnnotation(t);// 方法上定义的
if (annotation == null) {
annotation = (T) pjp.getSignature().getDeclaringType().getAnnotation(t);// 类上定义的
if (annotation == null) {
Object target = pjp.getTarget();
annotation = target.getClass().getAnnotation(t);// 实现类上定义的
if (annotation == null) {
Signature sig = pjp.getSignature();
if (sig instanceof MethodSignature) {
MethodSignature msig = (MethodSignature) sig;
Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
annotation = currentMethod.getAnnotation(t);// 实现类的方法上定义的
}
}
}
}
return annotation;
}
}

View File

@@ -3,8 +3,7 @@ package com.zyplayer.doc.manage.framework.config;
import com.alibaba.fastjson.serializer.SerializerFeature; import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig; import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.zyplayer.doc.data.config.DocLoginOriginInterceptor; import com.zyplayer.doc.manage.framework.interceptor.UserLoginInterceptor;
import com.zyplayer.doc.manage.framework.interceptor.RequestInfoInterceptor;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry; import org.springframework.format.FormatterRegistry;
@@ -13,11 +12,11 @@ import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -25,12 +24,10 @@ import java.util.List;
@Component @Component
@Configuration @Configuration
public class WebMvcConfig implements WebMvcConfigurer { public class WebMvcConfig implements WebMvcConfigurer {
@Resource @Resource
RequestInfoInterceptor requestInfoInterceptor; UserLoginInterceptor userLoginInterceptor;
@Resource
DocLoginOriginInterceptor docLoginOriginInterceptor;
@Override @Override
public void addFormatters(FormatterRegistry registry) { public void addFormatters(FormatterRegistry registry) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@@ -40,12 +37,12 @@ public class WebMvcConfig implements WebMvcConfigurer {
dateFormatter.setLenient(true); dateFormatter.setLenient(true);
registry.addFormatter(dateFormatter); registry.addFormatter(dateFormatter);
} }
@Bean @Bean
public FastJsonHttpMessageConverter fastJsonHttpMessageConverter() { public FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {
FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter(); FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
List<MediaType> supportedMediaTypes = new ArrayList<>(); List<MediaType> supportedMediaTypes = new ArrayList<>();
supportedMediaTypes.add(new MediaType("application", "json", Charset.forName("UTF-8"))); supportedMediaTypes.add(new MediaType("application", "json", StandardCharsets.UTF_8));
fastJsonHttpMessageConverter.setSupportedMediaTypes(supportedMediaTypes); fastJsonHttpMessageConverter.setSupportedMediaTypes(supportedMediaTypes);
FastJsonConfig fastJsonConfig = new FastJsonConfig(); FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteDateUseDateFormat); fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteDateUseDateFormat);
@@ -57,12 +54,10 @@ public class WebMvcConfig implements WebMvcConfigurer {
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(0, fastJsonHttpMessageConverter()); converters.add(0, fastJsonHttpMessageConverter());
} }
@Override @Override
public void addInterceptors(InterceptorRegistry registry) { public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(docLoginOriginInterceptor); registry.addInterceptor(userLoginInterceptor).excludePathPatterns("/**/*.js", "/**/*.css", "/**/*.png", "/**/*.gif", "/**/*.jpg", "/**/*.jpeg", "/**/fonts/*");
registry.addInterceptor(requestInfoInterceptor).excludePathPatterns("/**/*.js", "/**/*.css", "/**/*.png",
"/**/*.gif", "/**/*.jpg", "/**/*.jpeg", "/**/fonts/*");
} }
} }

View File

@@ -1,38 +0,0 @@
package com.zyplayer.doc.manage.framework.interceptor;
import javax.servlet.ServletContext;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
import org.springframework.web.context.ServletContextAware;
/**
* 所有bean初始化后执行bean初始化了再初始化一些自己的东西
*/
@Component
public class InitServletContextAware implements InitializingBean,ServletContextAware {
private ServletContext context;
@Override
public void setServletContext(ServletContext context) {
this.context = context;
}
@Override
public void afterPropertiesSet() throws Exception {
ctx();
}
private void ctx(){
String ctx = context.getContextPath();
if (ctx != null && ctx.trim().length() > 0 && !ctx.trim().equals("/")) {
context.setAttribute("ctx", ctx+"/");
context.setAttribute("statics", ctx+"/statics/");
} else {
context.setAttribute("ctx", "/");
context.setAttribute("statics", "/statics/");
}
}
}

View File

@@ -1,55 +0,0 @@
package com.zyplayer.doc.manage.framework.interceptor;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.server.HttpServerRequest;
import com.zyplayer.doc.core.util.ThreadLocalUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Optional;
/**
* 记录当前请求信息
*/
@Component
public class RequestInfoInterceptor implements HandlerInterceptor {
private static final Logger logger = LoggerFactory.getLogger(RequestInfoInterceptor.class);
private ThreadLocal<Long> startTimeThreadLocal = new ThreadLocal<>();
/**
* 把当前请求记录到下来
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object arg2, Exception arg3) {
Long startTime = startTimeThreadLocal.get();
startTime = Optional.ofNullable(startTime).orElse(System.currentTimeMillis());
long totalTime = System.currentTimeMillis() - startTime;// 结束时间
String clientIP = ServletUtil.getClientIP(request);
logger.info("IP{},总耗时:{}msURI{}", clientIP, totalTime, request.getRequestURI());
ThreadLocalUtil.clean();
startTimeThreadLocal.remove();
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object haddler, ModelAndView modelAndView) {
}
/**
* 记录请求信息
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object obj) {
response.setContentType("application/json; charset=utf-8"); // 设定JSON格式标准输出、及编码
startTimeThreadLocal.set(System.currentTimeMillis());
ThreadLocalUtil.setHttpServletRequest(request);
return true;
}
}

View File

@@ -0,0 +1,101 @@
package com.zyplayer.doc.manage.framework.interceptor;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.http.HttpUtil;
import com.zyplayer.doc.core.annotation.AuthMan;
import com.zyplayer.doc.core.json.DocResponseJson;
import com.zyplayer.doc.core.json.HttpConst;
import com.zyplayer.doc.core.util.ThreadLocalUtil;
import com.zyplayer.doc.data.config.security.DocUserDetails;
import com.zyplayer.doc.data.config.security.DocUserUtil;
import org.apache.catalina.util.RequestUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Optional;
/**
* 用户登录拦截
*/
@Component
public class UserLoginInterceptor implements HandlerInterceptor {
private static final Logger logger = LoggerFactory.getLogger(UserLoginInterceptor.class);
@Value("${zyplayer.doc.manage.originDomainRegex:}")
private String originDomainRegex;
private final ThreadLocal<Long> startTimeThreadLocal = new ThreadLocal<>();
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object arg2, Exception arg3) {
Long startTime = startTimeThreadLocal.get();
startTime = Optional.ofNullable(startTime).orElse(System.currentTimeMillis());
long totalTime = System.currentTimeMillis() - startTime;
String clientIP = ServletUtil.getClientIP(request);
logger.info("IP{},总耗时:{}msURI{}", clientIP, totalTime, request.getRequestURI());
ThreadLocalUtil.clean();
startTimeThreadLocal.remove();
// 清理用户信息
DocUserUtil.clean();
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
startTimeThreadLocal.set(System.currentTimeMillis());
ThreadLocalUtil.setHttpServletRequest(request);
// 指定域名可跨域访问
if (StringUtils.isNotBlank(originDomainRegex)) {
String origin = request.getHeader("Origin");
if (StringUtils.isNotBlank(origin) && origin.toLowerCase().matches(originDomainRegex)) {
response.setHeader("Access-Control-Allow-Origin", origin); // 允许访问的域
response.setHeader("Access-Control-Allow-Methods", "HEAD,GET,POST,PUT,DELETE");// 允许GET、POST的外域请求
response.setHeader("Access-Control-Allow-Credentials", "true"); // 允许请求带cookie到服务器
response.setContentType("application/json; charset=utf-8"); // 设定JSON格式标准输出、及编码
}
}
if (!(handler instanceof HandlerMethod)) {
return true;
}
// 清理用户信息
DocUserUtil.clean();
// 设置token
Cookie cookie = ServletUtil.getCookie(request, HttpConst.ACCESS_TOKEN);
String accessToken = (cookie == null) ? null : cookie.getValue();
DocUserUtil.setAccessToken(accessToken);
AuthMan authMan = ((HandlerMethod) handler).getMethod().getAnnotation(AuthMan.class);
if (authMan == null) {
authMan = ((HandlerMethod) handler).getMethod().getDeclaringClass().getAnnotation(AuthMan.class);
if (authMan == null) {
return true;
}
}
DocUserDetails currentUser = DocUserUtil.getCurrentUser();
if (currentUser == null) {
String reason = "你访问的内容需要登录,请登录后再试";
DocResponseJson.failure(HttpConst.TOKEN_TIMEOUT, reason).send(response);
return false;
}
// 判断权限是否足够
boolean haveAuth = DocUserUtil.haveAuth(authMan.value());
if (haveAuth) {
return true;
}
String reasonStr = "没有操作权限,请联系管理员";
DocResponseJson.warn(reasonStr).send(response);
return false;
}
}

View File

@@ -20,6 +20,7 @@ import springfox.documentation.swagger.web.SwaggerResource;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@@ -76,8 +77,13 @@ public class SwaggerDocumentController {
String docUrl = SwaggerDocUtil.replaceSwaggerResources(swaggerDoc.getDocUrl()); String docUrl = SwaggerDocUtil.replaceSwaggerResources(swaggerDoc.getDocUrl());
if (SwaggerDocUtil.isSwaggerResources(docUrl)) { if (SwaggerDocUtil.isSwaggerResources(docUrl)) {
String swaggerDomain = SwaggerDocUtil.getSwaggerResourceDomain(docUrl); String swaggerDomain = SwaggerDocUtil.getSwaggerResourceDomain(docUrl);
String resourcesStr = swaggerHttpRequestService.requestSwaggerUrl(request, docUrl, swaggerDomain); List<SwaggerResource> resourceList;
List<SwaggerResource> resourceList = JSON.parseArray(resourcesStr, SwaggerResource.class); try {
String resourcesStr = swaggerHttpRequestService.requestSwaggerUrl(request, docUrl, swaggerDomain);
resourceList = JSON.parseArray(resourcesStr, SwaggerResource.class);
} catch (Exception e) {
return DocResponseJson.warn("解析文档地址失败:" + e.getMessage());
}
if (resourceList == null || resourceList.isEmpty()) { if (resourceList == null || resourceList.isEmpty()) {
return DocResponseJson.warn("该地址未找到文档"); return DocResponseJson.warn("该地址未找到文档");
} }

View File

@@ -2,6 +2,7 @@ package com.zyplayer.doc.swaggerplus.controller;
import com.zyplayer.doc.core.annotation.AuthMan; import com.zyplayer.doc.core.annotation.AuthMan;
import com.zyplayer.doc.core.exception.ConfirmException; import com.zyplayer.doc.core.exception.ConfirmException;
import com.zyplayer.doc.core.json.DocResponseJson;
import com.zyplayer.doc.data.repository.manage.entity.SwaggerDoc; import com.zyplayer.doc.data.repository.manage.entity.SwaggerDoc;
import com.zyplayer.doc.data.service.manage.SwaggerDocService; import com.zyplayer.doc.data.service.manage.SwaggerDocService;
import com.zyplayer.doc.swaggerplus.controller.vo.SwaggerResourceVo; import com.zyplayer.doc.swaggerplus.controller.vo.SwaggerResourceVo;
@@ -37,6 +38,7 @@ public class SwaggerProxyController {
@Resource @Resource
private SwaggerHttpRequestService swaggerHttpRequestService; private SwaggerHttpRequestService swaggerHttpRequestService;
@ResponseBody
@RequestMapping("/swagger-resources") @RequestMapping("/swagger-resources")
public List<SwaggerResourceVo> swaggerResources() { public List<SwaggerResourceVo> swaggerResources() {
List<SwaggerResourceVo> resourceList = new LinkedList<>(); List<SwaggerResourceVo> resourceList = new LinkedList<>();
@@ -57,15 +59,19 @@ public class SwaggerProxyController {
@ResponseBody @ResponseBody
@RequestMapping(value = "/v2/api-docs", produces = {MimeTypeUtils.APPLICATION_JSON_VALUE, HAL_MEDIA_TYPE}) @RequestMapping(value = "/v2/api-docs", produces = {MimeTypeUtils.APPLICATION_JSON_VALUE, HAL_MEDIA_TYPE})
public ResponseEntity<Json> content(HttpServletRequest request, Long id) { public ResponseEntity<Object> content(HttpServletRequest request, Long id) {
SwaggerDoc swaggerDoc = swaggerDocService.getById(id); SwaggerDoc swaggerDoc = swaggerDocService.getById(id);
if (swaggerDoc == null) { if (swaggerDoc == null) {
throw new ConfirmException("文档不存在"); throw new ConfirmException("文档不存在");
} }
if (Objects.equals(swaggerDoc.getDocType(), 1)) { if (Objects.equals(swaggerDoc.getDocType(), 1)) {
String docsDomain = SwaggerDocUtil.getV2ApiDocsDomain(swaggerDoc.getDocUrl()); try {
String contentStr = swaggerHttpRequestService.requestSwaggerUrl(request, swaggerDoc.getDocUrl(), docsDomain); String docsDomain = SwaggerDocUtil.getV2ApiDocsDomain(swaggerDoc.getDocUrl());
return new ResponseEntity<>(new Json(contentStr), HttpStatus.OK); String contentStr = swaggerHttpRequestService.requestSwaggerUrl(request, swaggerDoc.getDocUrl(), docsDomain);
return new ResponseEntity<>(new Json(contentStr), HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(DocResponseJson.warn("请求文档失败"), HttpStatus.OK);
}
} }
return new ResponseEntity<>(new Json(swaggerDoc.getJsonContent()), HttpStatus.OK); return new ResponseEntity<>(new Json(swaggerDoc.getJsonContent()), HttpStatus.OK);
} }