初始代码
This commit is contained in:
27
yunzhupaas-boot-common/yunzhupaas-common-security/pom.xml
Normal file
27
yunzhupaas-boot-common/yunzhupaas-common-security/pom.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>yunzhupaas-boot-common</artifactId>
|
||||
<groupId>com.yunzhupaas</groupId>
|
||||
<version>5.2.0-RELEASE</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>yunzhupaas-common-security</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.yunzhupaas</groupId>
|
||||
<artifactId>yunzhupaas-common-auth</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.yunzhupaas</groupId>
|
||||
<artifactId>yunzhupaas-common-database</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,150 @@
|
||||
package com.yunzhupaas.config;
|
||||
|
||||
import cn.dev33.satoken.context.SaHolder;
|
||||
import cn.dev33.satoken.fun.strategy.SaCheckElementAnnotationFunction;
|
||||
import cn.dev33.satoken.interceptor.SaInterceptor;
|
||||
import cn.dev33.satoken.same.SaSameUtil;
|
||||
import cn.dev33.satoken.strategy.SaStrategy;
|
||||
import com.yunzhupaas.annotation.SaCheckSame;
|
||||
import com.yunzhupaas.base.UserInfo;
|
||||
import com.yunzhupaas.consts.AuthConsts;
|
||||
import com.yunzhupaas.filter.ClearThreadContextFilter;
|
||||
import com.yunzhupaas.filter.RequestWrapperFilter;
|
||||
import com.yunzhupaas.filter.SecurityFilter;
|
||||
import com.yunzhupaas.handler.IRestHandler;
|
||||
import com.yunzhupaas.encrypt.EncryptRestInterceptor;
|
||||
import com.yunzhupaas.properties.SecurityProperties;
|
||||
import com.yunzhupaas.util.StringUtil;
|
||||
import com.yunzhupaas.util.UserProvider;
|
||||
import com.yunzhupaas.util.context.SpringContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import jakarta.servlet.*;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author 云筑产品开发平台组
|
||||
* @copyright 深圳市乐程软件有限公司
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
|
||||
public class SecurityConfiguration implements WebMvcConfigurer {
|
||||
|
||||
|
||||
@Autowired
|
||||
private SecurityProperties securityProperties;
|
||||
|
||||
/**
|
||||
* 注册sa-token的拦截器
|
||||
*/
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
initSaInterfaceAuth(registry);
|
||||
initEncryptRestInterceptor(registry);
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求封装过滤器
|
||||
*/
|
||||
@Bean("myRequestWrapperFilter")
|
||||
@ConditionalOnMissingBean(name = "myRequestWrapperFilter")
|
||||
public Filter getRequestWrapperFilter(List<IRestHandler> handlers){
|
||||
return new RequestWrapperFilter(handlers, securityProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* 线程变量清除过滤器
|
||||
*/
|
||||
@Bean("myClearThreadContextFilter")
|
||||
@ConditionalOnMissingBean(name = "myClearThreadContextFilter")
|
||||
public Filter getClearThreadContextFilter(){
|
||||
return new ClearThreadContextFilter();
|
||||
}
|
||||
|
||||
/**
|
||||
* 来源验证、用户、租户设置过滤器
|
||||
*/
|
||||
@Bean("mySecurityFilter")
|
||||
@ConditionalOnMissingBean(name = "mySecurityFilter")
|
||||
public Filter getSecurityFilter(SecurityProperties securityProperties, ConfigValueUtil configValueUtil){
|
||||
return new SecurityFilter(securityProperties, configValueUtil).addInclude("/**");
|
||||
}
|
||||
/**
|
||||
* 传输加密
|
||||
*/
|
||||
@Bean("myEncryptRestInterceptor")
|
||||
@ConditionalOnMissingBean(name = "myEncryptRestInterceptor")
|
||||
@ConditionalOnProperty(prefix = "security", name = "enable-rest-encrypt", havingValue = "true")
|
||||
public HandlerInterceptor getEncryptRestInterceptor(){
|
||||
return new EncryptRestInterceptor();
|
||||
}
|
||||
|
||||
protected void initEncryptRestInterceptor(InterceptorRegistry registry){
|
||||
if(securityProperties.isEnableRestEncrypt()){
|
||||
registry.addInterceptor(SpringContext.getBean("myEncryptRestInterceptor"));
|
||||
}
|
||||
}
|
||||
|
||||
protected void initSaInterfaceAuth(InterceptorRegistry registry){
|
||||
if(securityProperties.isEnablePreAuth()) {
|
||||
// 旧注解校验方法
|
||||
SaCheckElementAnnotationFunction oldCheckElementAnnotation = SaStrategy.instance.checkElementAnnotation;
|
||||
SaStrategy.instance.checkElementAnnotation = (element) -> {
|
||||
// 添加内部请求校验
|
||||
SaCheckSame checkRole = (SaCheckSame) SaStrategy.instance.getAnnotation.apply(element, SaCheckSame.class);
|
||||
if(checkRole != null){
|
||||
SaSameUtil.checkToken(SaHolder.getRequest().getHeader(AuthConsts.INNER_TOKEN_KEY));
|
||||
}
|
||||
// 调用旧注解校验
|
||||
oldCheckElementAnnotation.accept(element);
|
||||
};
|
||||
// 开启接口请求权限控制
|
||||
registry.addInterceptor(new SaInterceptor((handler) -> {
|
||||
|
||||
}).isAnnotation(securityProperties.isEnablePreAuth())).addPathPatterns("/**");
|
||||
}
|
||||
//接口鉴权忽略管理员、内部请求
|
||||
BiFunction<List<String>, String, Boolean> oldCheckFunc = SaStrategy.instance.hasElement;
|
||||
SaStrategy.instance.hasElement = (list, element) -> {
|
||||
//启用之后才验证
|
||||
if (securityProperties.isEnablePreAuth()) {
|
||||
UserInfo userInfo = UserProvider.getUser();
|
||||
//未获取到用户信息返回false
|
||||
if (StringUtil.isEmpty(userInfo.getUserId())) {
|
||||
return false;
|
||||
}
|
||||
//管理员返回true
|
||||
if (userInfo.getIsAdministrator()) {
|
||||
return true;
|
||||
}
|
||||
boolean result = oldCheckFunc.apply(list, element);
|
||||
//如果鉴权失败, 检测是否来自内部请求
|
||||
if (!result) {
|
||||
String innerToken = SaHolder.getRequest().getHeader(AuthConsts.INNER_TOKEN_KEY);
|
||||
//来自内部请求(非网关) 无需鉴权
|
||||
if (UserProvider.isValidInnerToken(innerToken)) {
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.yunzhupaas.encrypt;
|
||||
|
||||
import com.yunzhupaas.handler.IRestHandler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@Order(0)
|
||||
@Component
|
||||
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
|
||||
@ConditionalOnProperty(prefix = "security", name = "enable-rest-encrypt", havingValue = "true")
|
||||
public class EmptyEncryptRestRequestHandler implements IRestHandler {
|
||||
|
||||
@Override
|
||||
public boolean supportParameter() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportBodyJson() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.yunzhupaas.encrypt;
|
||||
|
||||
import cn.hutool.core.util.HexUtil;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.yunzhupaas.annotation.EncryptApi;
|
||||
import com.yunzhupaas.properties.SecurityProperties;
|
||||
import com.yunzhupaas.util.DesUtil;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
|
||||
|
||||
@ControllerAdvice
|
||||
public class EncryptResponseAdvice implements ResponseBodyAdvice<Object> {
|
||||
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
public EncryptResponseAdvice(ObjectMapper objectMapper) {
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
|
||||
EncryptApi methodAnnotation = returnType.getMethodAnnotation(EncryptApi.class);
|
||||
return methodAnnotation != null && methodAnnotation.encryptResponse();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
|
||||
try {
|
||||
byte[] bytes = objectMapper.writeValueAsBytes(body);
|
||||
return HexUtil.encodeHexStr(DesUtil.aesOrDecode(bytes, true, true, SecurityProperties.getInstance().getSecurityKey()));
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
package com.yunzhupaas.encrypt;
|
||||
|
||||
import cn.hutool.core.net.url.UrlQuery;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import com.yunzhupaas.annotation.EncryptApi;
|
||||
import com.yunzhupaas.constant.GlobalConst;
|
||||
import com.yunzhupaas.constant.MsgCode;
|
||||
import com.yunzhupaas.exception.EncryptFailException;
|
||||
import com.yunzhupaas.util.DesUtil;
|
||||
import com.yunzhupaas.util.StringUtil;
|
||||
import com.yunzhupaas.wrapper.MyRequestWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.AsyncHandlerInterceptor;
|
||||
|
||||
import java.net.URLDecoder;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 接口传输加密
|
||||
* 支持请求类型:
|
||||
* application/json
|
||||
* application/x-www-form-urlencoded
|
||||
*/
|
||||
@Slf4j
|
||||
public class EncryptRestInterceptor implements AsyncHandlerInterceptor {
|
||||
|
||||
private static final String ENCRYPT_KEY = "encryptData";
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
|
||||
throws Exception {
|
||||
try {
|
||||
if (handler instanceof HandlerMethod && request instanceof MyRequestWrapper) {
|
||||
HandlerMethod method = (HandlerMethod) handler;
|
||||
EncryptApi methodAnnotation = method.getMethodAnnotation(EncryptApi.class);
|
||||
if (methodAnnotation != null && methodAnnotation.encryptRequest()) {
|
||||
MyRequestWrapper myRequest = (MyRequestWrapper) request;
|
||||
// 需要对数据进行加密解密
|
||||
// application/json
|
||||
// application/x-www-form-urlencoded
|
||||
String contentType = request.getContentType();
|
||||
if (contentType != null) {
|
||||
String requestBody = null;
|
||||
boolean canEncrypt = false;
|
||||
if ((StringUtils.substringMatch(contentType, 0,
|
||||
MediaType.APPLICATION_FORM_URLENCODED_VALUE))
|
||||
|| "get".equalsIgnoreCase(request.getMethod())) {
|
||||
// 1.application/x-www-form-urlencoded 支持参数在body或者在param
|
||||
canEncrypt = true;
|
||||
requestBody = convertFormToString(request);
|
||||
if ("{}".equals(requestBody)) {
|
||||
requestBody = URLDecoder.decode(myRequest.getRequestBody());
|
||||
Map<CharSequence, CharSequence> uriToListToMap = new UrlQuery()
|
||||
.parse(requestBody, GlobalConst.DEFAULT_CHARSET).getQueryMap();
|
||||
requestBody = JSONObject.toJSONString(uriToListToMap);
|
||||
}
|
||||
|
||||
} else if (StringUtils.substringMatch(contentType, 0, MediaType.APPLICATION_JSON_VALUE)) {
|
||||
// application/json 支持加密参数在body
|
||||
canEncrypt = true;
|
||||
requestBody = myRequest.getRequestBody();
|
||||
}
|
||||
if (canEncrypt) {
|
||||
if (requestBody != null && !"{}".equals(requestBody)) {
|
||||
JSONObject jsonBody = JSON.parseObject(requestBody);
|
||||
JSON result = decodeApi(jsonBody);
|
||||
if (result != null) {
|
||||
myRequest.setRequestBody(result.toJSONString());
|
||||
if (result instanceof JSONObject) {
|
||||
myRequest.addAllParameters((Map<String, Object>) result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
throw encryptFailException();
|
||||
}
|
||||
}
|
||||
} catch (EncryptFailException eex) {
|
||||
throw eex;
|
||||
} catch (Exception e) {
|
||||
log.error("解密失败, 异常地址:{}", request.getServletPath(), e);
|
||||
throw encryptFailException();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pamams参数转JSON字符串
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
private String convertFormToString(HttpServletRequest request) {
|
||||
Map<String, String> result = new HashMap<>(8);
|
||||
Enumeration<String> parameterNames = request.getParameterNames();
|
||||
while (parameterNames.hasMoreElements()) {
|
||||
String name = parameterNames.nextElement();
|
||||
result.put(name, request.getParameter(name));
|
||||
}
|
||||
try {
|
||||
return JSON.toJSONString(result);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求内容解密
|
||||
*
|
||||
* @param body
|
||||
* @return
|
||||
*/
|
||||
public JSON decodeApi(JSON body) {
|
||||
try {
|
||||
JSONObject jsonObject = (JSONObject) body;
|
||||
String content = jsonObject.getOrDefault(ENCRYPT_KEY, "").toString();
|
||||
if (!StringUtil.isEmpty(content)) {
|
||||
content = decryptData(content);
|
||||
return (JSON) JSON.parse(content);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("解密失败, 文本: {}", body, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文本解密
|
||||
*
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
protected String decryptData(String data) {
|
||||
if (StringUtil.isEmpty(data)) {
|
||||
return data;
|
||||
}
|
||||
if (Objects.equals(data.charAt(0), '"') && Objects.equals(data.charAt(data.length() - 1), '"')) {
|
||||
data = data.substring(1, data.length() - 1);
|
||||
}
|
||||
return DesUtil.aesOrDecode(data, false, true);
|
||||
}
|
||||
|
||||
private EncryptFailException encryptFailException() {
|
||||
throw new EncryptFailException(MsgCode.FA051.get());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.yunzhupaas.filter;
|
||||
|
||||
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
|
||||
import com.yunzhupaas.database.util.IgnoreLogicDeleteHolder;
|
||||
import com.yunzhupaas.database.util.NotTenantPluginHolder;
|
||||
import com.yunzhupaas.database.util.TenantDataSourceUtil;
|
||||
import com.yunzhupaas.util.TenantProvider;
|
||||
import com.yunzhupaas.util.UserProvider;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 线程缓存清理
|
||||
*/
|
||||
@Order(-99)
|
||||
public class ClearThreadContextFilter extends OncePerRequestFilter {
|
||||
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||
try {
|
||||
filterChain.doFilter(request, response);
|
||||
}finally {
|
||||
//清除线程缓存
|
||||
UserProvider.clearLocalUser();
|
||||
TenantProvider.clearBaseSystemIfo();
|
||||
TenantDataSourceUtil.clearLocalTenantInfo();
|
||||
DynamicDataSourceContextHolder.clear();
|
||||
NotTenantPluginHolder.clearNotSwitchFlag();
|
||||
IgnoreLogicDeleteHolder.clear();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.yunzhupaas.filter;
|
||||
|
||||
import cn.dev33.satoken.context.SaHolder;
|
||||
import com.yunzhupaas.handler.IRestHandler;
|
||||
import com.yunzhupaas.properties.SecurityProperties;
|
||||
import com.yunzhupaas.util.PathUtil;
|
||||
import com.yunzhupaas.wrapper.MyRequestWrapper;
|
||||
import com.yunzhupaas.wrapper.MyResponseWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 请求内容
|
||||
*/
|
||||
@Slf4j
|
||||
@Order(-97)
|
||||
public class RequestWrapperFilter extends OncePerRequestFilter {
|
||||
|
||||
private List<IRestHandler> handlers;
|
||||
private SecurityProperties securityProperties;
|
||||
|
||||
public RequestWrapperFilter(List<IRestHandler> handlers, SecurityProperties securityProperties) {
|
||||
this.handlers = handlers;
|
||||
this.securityProperties = securityProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||
if(handlers.isEmpty()){
|
||||
filterChain.doFilter(request, response);
|
||||
} else {
|
||||
MyRequestWrapper myRequest = new MyRequestWrapper(request, handlers);
|
||||
MyResponseWrapper wrapResponse = new MyResponseWrapper(response, handlers);
|
||||
filterChain.doFilter(myRequest, wrapResponse);
|
||||
wrapResponse.doFinal();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.yunzhupaas.filter;
|
||||
|
||||
import cn.dev33.satoken.context.SaHolder;
|
||||
import cn.dev33.satoken.filter.SaServletFilter;
|
||||
import cn.dev33.satoken.router.SaRouter;
|
||||
import com.yunzhupaas.base.UserInfo;
|
||||
import com.yunzhupaas.config.ConfigValueUtil;
|
||||
import com.yunzhupaas.constant.MsgCode;
|
||||
import com.yunzhupaas.consts.AuthConsts;
|
||||
import com.yunzhupaas.database.util.TenantDataSourceUtil;
|
||||
import com.yunzhupaas.properties.SecurityProperties;
|
||||
import com.yunzhupaas.util.StringUtil;
|
||||
import com.yunzhupaas.util.UserProvider;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@Slf4j
|
||||
@Order(-98)
|
||||
public class SecurityFilter extends SaServletFilter {
|
||||
|
||||
|
||||
private SecurityProperties securityProperties;
|
||||
|
||||
private ConfigValueUtil configValueUtil;
|
||||
|
||||
public SecurityFilter(SecurityProperties securityProperties, ConfigValueUtil configValueUtil) {
|
||||
this.securityProperties = securityProperties;
|
||||
this.configValueUtil = configValueUtil;
|
||||
setAuth(o -> {
|
||||
initAuthenticationInfo();
|
||||
});
|
||||
setBeforeAuth(o -> {
|
||||
checkRequestOrigin.test(null);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求来源验证
|
||||
*/
|
||||
private Predicate<Object> checkRequestOrigin = t -> true;
|
||||
|
||||
|
||||
protected void initAuthenticationInfo(){
|
||||
//执行Token续期, 存用户信息至本地缓存后续无需重新获取
|
||||
UserProvider.renewTimeout();
|
||||
//设置租户信息
|
||||
if(configValueUtil.isMultiTenancy()) {
|
||||
UserInfo userInfo = UserProvider.getUser();
|
||||
if (StringUtil.isNotEmpty(userInfo.getTenantId())) {
|
||||
TenantDataSourceUtil.switchTenant(userInfo.getTenantId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 微服务才验证请求来源
|
||||
*/
|
||||
@ConditionalOnClass(name = "org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient")
|
||||
@PostConstruct
|
||||
public void onCloudCheckRequestOrigin(){
|
||||
checkRequestOrigin = t -> {
|
||||
//验证请求来源, 网关, Feign
|
||||
if(securityProperties.isEnableInnerAuth()) {
|
||||
SaRouter.match("/favicon.ico").stop();
|
||||
SaRouter.match("/**").match(r->{
|
||||
String innerToken = SaHolder.getRequest().getHeader(AuthConsts.INNER_TOKEN_KEY);
|
||||
String innerGatewayToken = SaHolder.getRequest().getHeader(AuthConsts.INNER_GATEWAY_TOKEN_KEY);
|
||||
if(!UserProvider.isValidInnerToken(innerGatewayToken) && !UserProvider.isValidInnerToken(innerToken)){
|
||||
log.error("非法请求: {}, {}", SaHolder.getRequest().getRequestPath(), innerToken);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}).back(MsgCode.FA034.get());
|
||||
}
|
||||
return true;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.yunzhupaas.handler;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface IRestHandler {
|
||||
|
||||
/**
|
||||
* 是否处理Header
|
||||
*/
|
||||
default boolean supportHeader(){
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否处理Form表单数据
|
||||
*/
|
||||
default boolean supportParameter(){
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否处理Body JSON
|
||||
*/
|
||||
default boolean supportBodyJson(){
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否处理返回结果
|
||||
*/
|
||||
default boolean supportResponse(){
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化Body JSON
|
||||
*/
|
||||
default JSON initBodyJson(JSON jsonContent){
|
||||
return jsonContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化Form表单数据
|
||||
*/
|
||||
default Map<String, String[]> initParameter(Map<String, String[]> parameter){
|
||||
return parameter;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理返回结果
|
||||
*/
|
||||
default String processResponse(String data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
package com.yunzhupaas.permissions;
|
||||
|
||||
import cn.dev33.satoken.session.SaSession;
|
||||
import cn.dev33.satoken.stp.StpInterface;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import com.yunzhupaas.base.UserInfo;
|
||||
import com.yunzhupaas.model.BaseSystemInfo;
|
||||
import com.yunzhupaas.properties.SecurityProperties;
|
||||
import com.yunzhupaas.util.TenantProvider;
|
||||
import com.yunzhupaas.util.UserProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static com.yunzhupaas.util.Constants.ADMIN_KEY;
|
||||
|
||||
|
||||
/**
|
||||
* 权限认证接口实现
|
||||
*
|
||||
* @author 云筑产品开发平台组
|
||||
* @copyright 深圳市乐程软件有限公司
|
||||
*/
|
||||
@Component
|
||||
public class PermissionInterfaceImpl implements StpInterface {
|
||||
|
||||
public static final String PERMISSION_KEY = "user_permission";
|
||||
public static final String ROLE_KEY = "user_roles";
|
||||
public static final String COLUMN_KEY = "user_columns";
|
||||
public static final String FORM_KEY = "user_forms";
|
||||
|
||||
@Autowired
|
||||
private SecurityProperties securityProperties;
|
||||
|
||||
@Override
|
||||
public List<String> getPermissionList(Object loginId, String loginType) {
|
||||
if (!securityProperties.isEnablePreAuth()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
UserInfo userInfo = UserProvider.getUser();
|
||||
String account = userInfo.getIsAdministrator() ? ADMIN_KEY : userInfo.getUserId();
|
||||
account = UserProvider.splicingLoginId(account);
|
||||
SaSession saSession = StpUtil.getSessionByLoginId(account, false);
|
||||
if (saSession == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return saSession.get(PERMISSION_KEY, Collections.emptyList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRoleList(Object loginId, String loginType) {
|
||||
if (!securityProperties.isEnablePreAuth()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
UserInfo userInfo = UserProvider.getUser();
|
||||
String account = userInfo.getIsAdministrator() ? ADMIN_KEY : userInfo.getUserId();
|
||||
account = UserProvider.splicingLoginId(account);
|
||||
SaSession saSession = StpUtil.getSessionByLoginId(account, false);
|
||||
if (saSession == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return saSession.get(ROLE_KEY, Collections.emptyList());
|
||||
}
|
||||
|
||||
public static Map<String, Object> getColumnMap() {
|
||||
UserInfo userInfo = UserProvider.getUser();
|
||||
String account = userInfo.getIsAdministrator() ? ADMIN_KEY : userInfo.getUserId();
|
||||
account = UserProvider.splicingLoginId(account);
|
||||
SaSession saSession = StpUtil.getSessionByLoginId(account, false);
|
||||
if (saSession == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
return saSession.get(COLUMN_KEY, Collections.emptyMap());
|
||||
}
|
||||
|
||||
public static Map<String, Object> getFormMap() {
|
||||
UserInfo userInfo = UserProvider.getUser();
|
||||
String account = userInfo.getIsAdministrator() ? ADMIN_KEY : userInfo.getUserId();
|
||||
account = UserProvider.splicingLoginId(account);
|
||||
SaSession saSession = StpUtil.getSessionByLoginId(account, false);
|
||||
if (saSession == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
return saSession.get(FORM_KEY, Collections.emptyMap());
|
||||
}
|
||||
|
||||
|
||||
public static void setAuthorityList(String userAccount, Set<String> authority, BaseSystemInfo baseSystemInfo) {
|
||||
userAccount = UserProvider.splicingLoginId(userAccount);
|
||||
try {
|
||||
TenantProvider.setBaseSystemInfo(baseSystemInfo);
|
||||
StpUtil.getSessionByLoginId(userAccount, true).set(PERMISSION_KEY, new ArrayList<>(authority));
|
||||
} finally {
|
||||
TenantProvider.clearBaseSystemIfo();
|
||||
}
|
||||
}
|
||||
|
||||
public static void setRoleList(String userAccount, Set<String> role, BaseSystemInfo baseSystemInfo) {
|
||||
userAccount = UserProvider.splicingLoginId(userAccount);
|
||||
try {
|
||||
TenantProvider.setBaseSystemInfo(baseSystemInfo);
|
||||
StpUtil.getSessionByLoginId(userAccount, true).set(ROLE_KEY, new ArrayList<>(role));
|
||||
} finally {
|
||||
TenantProvider.clearBaseSystemIfo();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void setColumnMap(String userAccount, Map<String, List<Map<String, Object>>> columnList, BaseSystemInfo baseSystemInfo) {
|
||||
userAccount = UserProvider.splicingLoginId(userAccount);
|
||||
try {
|
||||
TenantProvider.setBaseSystemInfo(baseSystemInfo);
|
||||
StpUtil.getSessionByLoginId(userAccount, true).set(COLUMN_KEY, columnList);
|
||||
} finally {
|
||||
TenantProvider.clearBaseSystemIfo();
|
||||
}
|
||||
}
|
||||
|
||||
public static void setFormMap(String userAccount, Map<String, List<Map<String, Object>>> formList, BaseSystemInfo baseSystemInfo) {
|
||||
userAccount = UserProvider.splicingLoginId(userAccount);
|
||||
try {
|
||||
TenantProvider.setBaseSystemInfo(baseSystemInfo);
|
||||
StpUtil.getSessionByLoginId(userAccount, true).set(FORM_KEY, formList);
|
||||
} finally {
|
||||
TenantProvider.clearBaseSystemIfo();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,240 @@
|
||||
package com.yunzhupaas.wrapper;
|
||||
|
||||
import cn.dev33.satoken.context.SaHolder;
|
||||
import cn.hutool.core.net.url.UrlQuery;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.yunzhupaas.constant.GlobalConst;
|
||||
import com.yunzhupaas.handler.IRestHandler;
|
||||
import com.yunzhupaas.util.StringUtil;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import jakarta.servlet.ReadListener;
|
||||
import jakarta.servlet.ServletInputStream;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequestWrapper;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Request封装
|
||||
* 处理类型:
|
||||
* application/json
|
||||
* application/x-www-form-urlencoded
|
||||
*/
|
||||
@Slf4j
|
||||
public class MyRequestWrapper extends HttpServletRequestWrapper {
|
||||
|
||||
protected Map<String, String[]> paramHashValues;
|
||||
@Getter
|
||||
@Setter
|
||||
protected String requestBody = null;
|
||||
protected HttpServletRequest req;
|
||||
|
||||
private final List<IRestHandler> handlers;
|
||||
|
||||
private final String[] EMPTY_ARRAY = new String[0];
|
||||
|
||||
/**
|
||||
* 是否需要处理Header, Body, Form
|
||||
*/
|
||||
private boolean supportHeader, supportBody, supportParameter;
|
||||
|
||||
public MyRequestWrapper(HttpServletRequest request, List<IRestHandler> handlers) throws IOException {
|
||||
super(request);
|
||||
this.req = request;
|
||||
this.handlers = handlers == null ? Collections.emptyList() : handlers;
|
||||
if(!handlers.isEmpty()){
|
||||
try {
|
||||
if (isJsonBodyRequest()) {
|
||||
processBody();
|
||||
} else if (isParameterRequest()) {
|
||||
processParameter();
|
||||
processFormBody();
|
||||
}
|
||||
} catch (Exception e){
|
||||
log.error("请求解析失败:{}", SaHolder.getRequest().getRequestPath());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processBody() throws IOException {
|
||||
List<IRestHandler> bodyHandlers = this.handlers.stream().filter(IRestHandler::supportBodyJson).collect(Collectors.toList());
|
||||
if (!bodyHandlers.isEmpty()) {
|
||||
this.requestBody = convertInputStreamToString(req.getInputStream());
|
||||
if (StringUtil.isNotEmpty(this.requestBody)) {
|
||||
JSON jsonData = (JSON) JSON.parse(this.requestBody);
|
||||
for (IRestHandler bodyHandler : bodyHandlers) {
|
||||
jsonData = bodyHandler.initBodyJson(jsonData);
|
||||
}
|
||||
requestBody = jsonData.toJSONString();
|
||||
supportBody = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processParameter(){
|
||||
List<IRestHandler> parameterHandlers = this.handlers.stream().filter(IRestHandler::supportParameter).collect(Collectors.toList());
|
||||
if (!parameterHandlers.isEmpty()) {
|
||||
paramHashValues = new HashMap<>();
|
||||
paramHashValues.putAll(req.getParameterMap());
|
||||
/*
|
||||
//解除锁定直接添加
|
||||
if(paramHashValues instanceof ParameterMap){
|
||||
((ParameterMap<String, String[]>) paramHashValues).setLocked(false);
|
||||
}
|
||||
*/
|
||||
parameterHandlers.forEach(h -> paramHashValues = h.initParameter(paramHashValues));
|
||||
supportParameter = true;
|
||||
}
|
||||
}
|
||||
private void processFormBody() throws IOException {
|
||||
List<IRestHandler> bodyHandlers = this.handlers.stream().filter(IRestHandler::supportBodyJson).collect(Collectors.toList());
|
||||
if (!bodyHandlers.isEmpty()) {
|
||||
this.requestBody = convertInputStreamToString(req.getInputStream());
|
||||
if(StringUtil.isNotEmpty(this.requestBody)){
|
||||
Map<CharSequence, CharSequence> uriToListToMap = new UrlQuery().parse(this.requestBody, GlobalConst.DEFAULT_CHARSET).getQueryMap();
|
||||
requestBody = JSONObject.toJSONString(uriToListToMap);
|
||||
}
|
||||
if (StringUtil.isNotEmpty(this.requestBody)) {
|
||||
JSON jsonData = (JSON) JSON.parse(this.requestBody);
|
||||
for (IRestHandler bodyHandler : bodyHandlers) {
|
||||
jsonData = bodyHandler.initBodyJson(jsonData);
|
||||
}
|
||||
Map<String, Object> formJson = (JSONObject) jsonData;
|
||||
UrlQuery urlQuery = new UrlQuery();
|
||||
for (Map.Entry<String, Object> entry : formJson.entrySet()) {
|
||||
urlQuery.add(entry.getKey(), entry.getValue());
|
||||
}
|
||||
requestBody = urlQuery.build(GlobalConst.DEFAULT_CHARSET);
|
||||
supportBody = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedReader getReader() throws IOException {
|
||||
if(supportBody){
|
||||
return new BufferedReader(new StringReader(requestBody));
|
||||
}else{
|
||||
return super.getReader();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletInputStream getInputStream() throws IOException {
|
||||
if(supportBody){
|
||||
return new ServletInputStream() {
|
||||
private InputStream in = new ByteArrayInputStream(
|
||||
requestBody.getBytes(req.getCharacterEncoding()));
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return in.read();
|
||||
}
|
||||
@Override
|
||||
public boolean isFinished() {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public void setReadListener(ReadListener readListener) {
|
||||
|
||||
}
|
||||
};
|
||||
}else {
|
||||
return super.getInputStream();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String[]> getParameterMap() {
|
||||
if(supportParameter){
|
||||
return this.paramHashValues;
|
||||
}else {
|
||||
return super.getParameterMap();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParameter(String name) {
|
||||
if(supportParameter){
|
||||
String[] parameter = this.paramHashValues.getOrDefault(name, EMPTY_ARRAY);
|
||||
return parameter.length == 0 ? null: parameter[0];
|
||||
}else {
|
||||
return super.getParameter(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getParameterValues(String name) {
|
||||
if(supportParameter){
|
||||
return this.paramHashValues.get(name);
|
||||
}else {
|
||||
return super.getParameterValues(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getParameterNames() {
|
||||
if(supportParameter){
|
||||
return Collections.enumeration(this.paramHashValues.keySet());
|
||||
}else {
|
||||
return super.getParameterNames();
|
||||
}
|
||||
}
|
||||
|
||||
public void addAllParameters(Map<String, Object> otherParams) {// 增加多个参数
|
||||
for (Map.Entry<String, Object> entry : otherParams.entrySet()) {
|
||||
addParameter(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void addParameter(String name, Object value) {// 增加参数
|
||||
if (value != null && paramHashValues != null) {
|
||||
if (value instanceof String[]) {
|
||||
paramHashValues.put(name, (String[]) value);
|
||||
} else if (value instanceof String) {
|
||||
paramHashValues.put(name, new String[]{(String) value});
|
||||
} else {
|
||||
paramHashValues.put(name, new String[]{String.valueOf(value)});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isParameterRequest(){
|
||||
String contentType = this.req.getContentType();
|
||||
if(StringUtil.isNotEmpty(contentType)) {
|
||||
if (StringUtils.substringMatch(contentType, 0, MediaType.APPLICATION_FORM_URLENCODED_VALUE)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean isJsonBodyRequest(){
|
||||
String contentType = this.req.getContentType();
|
||||
if(StringUtil.isNotEmpty(contentType)) {
|
||||
if (StringUtils.substringMatch(contentType, 0, MediaType.APPLICATION_JSON_VALUE)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected String convertInputStreamToString(InputStream inputStream) throws IOException {
|
||||
return StreamUtils.copyToString(inputStream, GlobalConst.DEFAULT_CHARSET);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
package com.yunzhupaas.wrapper;
|
||||
|
||||
import com.yunzhupaas.constant.GlobalConst;
|
||||
import com.yunzhupaas.handler.IRestHandler;
|
||||
import com.yunzhupaas.util.StringUtil;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import jakarta.servlet.ServletOutputStream;
|
||||
import jakarta.servlet.WriteListener;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpServletResponseWrapper;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Response封装
|
||||
* 处理类型:
|
||||
* application/json
|
||||
*/
|
||||
public class MyResponseWrapper extends HttpServletResponseWrapper {
|
||||
private ByteArrayOutputStream buffer;
|
||||
private ServletOutputStream out = null;
|
||||
private PrintWriter writer = null;
|
||||
|
||||
private List<IRestHandler> handlers;
|
||||
private boolean supportResponse;
|
||||
|
||||
public MyResponseWrapper(HttpServletResponse resp, List<IRestHandler> handlers) throws IOException {
|
||||
super(resp);
|
||||
this.handlers = handlers.stream().filter(IRestHandler::supportResponse).collect(Collectors.toList());
|
||||
supportResponse = !handlers.isEmpty();
|
||||
//返回处理器顺序翻转
|
||||
Collections.reverse(handlers);
|
||||
if(supportResponse) {
|
||||
buffer = new ByteArrayOutputStream();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletOutputStream getOutputStream() throws IOException {
|
||||
if(supportResponse) {
|
||||
if (out == null) {
|
||||
out = new WapperedOutputStream(buffer);
|
||||
}
|
||||
return out;
|
||||
}else{
|
||||
return super.getOutputStream();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrintWriter getWriter() throws IOException {
|
||||
if(supportResponse) {
|
||||
if (writer == null) {
|
||||
writer = new PrintWriter(new OutputStreamWriter(buffer, this.getCharacterEncoding()));
|
||||
}
|
||||
return writer;
|
||||
}else{
|
||||
return super.getWriter();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushBuffer() throws IOException {
|
||||
if(supportResponse) {
|
||||
if (out != null) {
|
||||
out.flush();
|
||||
}
|
||||
if (writer != null) {
|
||||
writer.flush();
|
||||
}
|
||||
}else{
|
||||
super.flushBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
if(supportResponse) {
|
||||
buffer.reset();
|
||||
}else{
|
||||
super.reset();
|
||||
}
|
||||
}
|
||||
|
||||
public void doFinal() throws IOException{
|
||||
if(supportResponse) {
|
||||
flushBuffer();
|
||||
if (buffer.size() > 0) {
|
||||
byte[] byteArray = buffer.toByteArray();
|
||||
if (supportResponse && isJsonBodyRequest()) {
|
||||
getResponse().setContentLength(-1);
|
||||
getResponse().setCharacterEncoding(GlobalConst.DEFAULT_CHARSET_STR);
|
||||
String data = new String(byteArray, GlobalConst.DEFAULT_CHARSET);
|
||||
for (IRestHandler handler : handlers) {
|
||||
data = handler.processResponse(data);
|
||||
}
|
||||
writeResponse(data);
|
||||
return;
|
||||
}
|
||||
writeResponse(byteArray);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writeResponse(String responseString)
|
||||
throws IOException {
|
||||
PrintWriter out = getResponse().getWriter();
|
||||
out.write(responseString);
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
|
||||
private void writeResponse(byte[] responseData) throws IOException {
|
||||
ServletOutputStream outputStream = getResponse().getOutputStream();
|
||||
outputStream.write(responseData);
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
}
|
||||
|
||||
private class WapperedOutputStream extends ServletOutputStream {
|
||||
private ByteArrayOutputStream bos = null;
|
||||
|
||||
public WapperedOutputStream(ByteArrayOutputStream stream) throws IOException {
|
||||
bos = stream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
bos.write(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWriteListener(WriteListener listener) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected boolean isJsonBodyRequest(){
|
||||
String contentType = getResponse().getContentType();
|
||||
if(StringUtil.isNotEmpty(contentType)) {
|
||||
if (StringUtils.substringMatch(contentType, 0, MediaType.APPLICATION_JSON_VALUE)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user