《中间件信息采集系统》项目经验(有不合理的地方请指出)

80 阅读4分钟

项目背景:

公司想要一个系统去收集各个部门都是使用了哪些中间件,该系统分期,每期都会下发任务表单。

场景1:发布表单

case0:直接分享表单的key。

如果是点击url会直接根据url的表单key查询表单详情

case1:分享url先base64加密再aes加密

问题1:浏览器会自动解码,将“+”号解码为null

解决方案:1.通过提前对字符编码再传输参数2.改变请求方式,content-type:的值。3.用框架

base64:

// java url安全的Base64编码
String urlSafeEncodeResult = Base64.getUrlEncoder().encodeToString(bytes);
byte[] urlSafeDecodeResult = Base64.getUrlDecoder().decode(urlSafeEncodeResult);

Base64从本质来说一种编码方式,分片一系列操作后,后根据Base64编码表,获取相应的编码值

AES:

对称加密(对称加密算法也就是加密和解密用相同的密钥)

对称加密算法与非对称加密算法的区别:

(1)对称加密算法:加密和解密用到的密钥是相同的,这种加密方式加密速度非常快,适合经常发送数据的场合。缺点是密钥的传输比较麻烦。

(2)非对称加密算法:加密和解密用的密钥是不同的,这种加密方式是用数学上的难解问题构造的,通常加密解密的速度比较慢,适合偶尔发送数据的场合。优点是密钥传输方便。常见的非对称加密算法为RSA。

有加密向量vi每次都会传递vi过去。提交后会做数据校验,说穿了就是看当前表单是不是当前登陆人部门的。 url:部门id+vi。

场景2:新增功能,停止发布,微信公众号

case0:(新增发布与停止发布功能)/+(SpringBoot+Websokect实现微信扫码自动登录)(开通公众号)+URL分享

新增发布与停止发布功能

发布:先传递一个表单的可以过来,再权限校验(当前登陆人是否是超管,是否是所有者),再检查当前表单是否存在,不存在直接报错,存在进行状态的更新为(收集中) 发布:先传递一个表单的可以过来,再权限校验(当前登陆人是否是超管,是否是所有者),进行状态的更新为(停止)

image.png 停止任务时,表单的发布也需要一起停止。

SpringBoot+Websokect实现微信扫码自动登录

参考文章:juejin.cn/post/723621…

1.登录公众号后台,配置接入URL和Token等

2.导入微信的jar包与yml配置

导入微信的jar包

<dependency>  
<groupId>com.github.binarywang</groupId>  
<artifactId>weixin-java-mp</artifactId>  
<version>${weixin-java.version}</version>  
</dependency>

yml配置

wx:  
mp:  
configs:  
- appId: #公众号appId  
secret: #公众号秘钥  
token: dHClTzEAc*******
aesKey: 3aNsbtc8wdx92M14******

3.通过@ConfigurationProperties将yml注入

4.接入公众号

其实本质就是调用微信jar包提供的方法去做一些判空和非法参数校验

5.编写扫码事件

6.websocket常量、WebsocketConfig核心配置类、WebSocketService缓存存储

websocket:stomp端点地址、订阅地址 WebsocketConfig:注册stomp端点,配置消息代理 WebSocketService:内存存储可用redis代替,将webSocket的token与http的认证token绑定在一起,这样便可以互相都找的到了,推送成功后移除。

场景3:XSS过滤处理(HttpServletRequestWrapper原理+HTMLfilter)

技术因素:HttpServletRequest没有提供set方法对前端参数进行修改,但是实际开发时需要过滤xss,所以HttpServletRequest就因势而生。

HttpServletRequestWrapper原理:采用装饰者模式模式对HttpServletRequest进行包装,通过继承HttpServletRequestWrapper 类去重写getParameterValues,getParameterh和获取原始的请求等方法, 实际还是调用HttpServletRequest的相对应方法,但是可以对方法的结果进行改装。

HTMLfilter:我也没看懂具体原理是撒,有懂个可以说一下。

代码展示:

public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {  
//html过滤  
private final static HTMLFilter htmlFilter = new HTMLFilter();  
//没被包装过的HttpServletRequest(特殊场景,需要自己过滤)  
HttpServletRequest orgRequest;  
@Getter  
private String bodyJson;  
  
public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {  
super(request);  
orgRequest = request;  
}  
  
/**  
* 获取最原始的request  
*/  
public static HttpServletRequest getOrgRequest(HttpServletRequest request) {  
if (request instanceof BodyReaderHttpServletRequestWrapper) {  
return ((BodyReaderHttpServletRequestWrapper) request).getOrgRequest();  
}  
  
return request;  
}  
  
@Override  
public ServletInputStream getInputStream() throws IOException {  
if (!MediaType.APPLICATION_JSON_VALUE.equalsIgnoreCase(super.getHeader(HttpHeaders.CONTENT_TYPE))) {  
return super.getInputStream();  
}  
if (StrUtil.isBlank(bodyJson)) {  
bodyJson = IOUtils.toString(super.getInputStream(), StandardCharsets.UTF_8);  
}  
final ByteArrayInputStream bis = new ByteArrayInputStream(bodyJson.getBytes(StandardCharsets.UTF_8));  
return new ServletInputStream() {  
@Override  
public boolean isFinished() {  
return true;  
}  
  
@Override  
public boolean isReady() {  
return true;  
}  
  
@Override  
public void setReadListener(ReadListener readListener) {  
  
}  
  
@Override  
public int read() throws IOException {  
return bis.read();  
}  
};  
}  
  
@Override  
public String getParameter(String name) {  
String value = super.getParameter(xssEncode(name));  
if (StrUtil.isNotBlank(value)) {  
value = xssEncode(value);  
}  
return value;  
}  
  
@Override  
public String[] getParameterValues(String name) {  
String[] parameters = super.getParameterValues(name);  
if (parameters == null || parameters.length == 0) {  
return null;  
}  
for (int i = 0; i < parameters.length; i++) {  
parameters[i] = xssEncode(parameters[i]);  
}  
return parameters;  
}  
  
//获取参数  
@Override  
public Map<String, String[]> getParameterMap() {  
//用LinkedHashMap是因为有序  
Map<String, String[]> map = new LinkedHashMap<>();  
//调用this.request.getParameter(name),其实就是调用ServletRequest的getParameterMap();  
Map<String, String[]> parameters = super.getParameterMap();  
// 通过hashMap得到key,通过key,再得到value参数  
for (String key : parameters.keySet()) {  
String[] values = parameters.get(key);  
for (int i = 0; i < values.length; i++) {  
//将每个参数传递给hutool的HTMLFilter,进行xss过滤  
values[i] = xssEncode(values[i]);  
}  
map.put(key, values);  
}  
return map;  
}  
  
@Override  
public String getHeader(String name) {  
String value = super.getHeader(xssEncode(name));  
if (StrUtil.isNotBlank(value)) {  
value = xssEncode(value);  
}  
return value;  
}  
  
private String xssEncode(String input) {  
return htmlFilter.filter(input);  
}  
  
/**  
* 获取最原始的request  
*/  
public HttpServletRequest getOrgRequest() {  
return orgRequest;  
}  
  
}