关于fastapi:项目中如何对XSS统一处理

XSS攻打是什么?XSS攻打是指攻击者利用网站中的破绽,向页面中注入歹意脚本,从而获取用户的信息或者管制用户的计算机。举一个艰深的例子,晚期应用JSP页面渲染页面的我的项目,如果将用户名改成nick<alert>1</alert>,则当用户关上页面时,就会弹出一个正告框,而这个正告框能够被歹意脚本所代替,例如读取cookies或者其余敏感信息等操作。如何在我的项目中防备XSS攻打呢有一些我的项目应用Filter+注解的形式来过滤或者提醒XSS攻打。通过在参数中的字段上加上相似@Xss的注解,来示意这个字段是不容许输出XSS脚本的。然而这种实现我感觉有几点不便之处。 严格来说,其实一般零碎内的绝大部分输出字段都不容许输出XSS文本。除非一些存储富文本的字段。因而须要在很多字段下来标注上@Xss注解。Filter中的代码,须要反复去读Request类的数据,因而须要本人实现一个可反复读的RequestWrapper. 因而我应用了JsonDeserializer更简略的解决全局的防Xss解决。残缺全局XSS对立解决实现在开源我的项目中:github.com/valarchie/A…原理Jackson框架容许自定义JsonDeserializer,因而能够在自定义的JsonDeserializer中剔除歹意XSS脚本注入。自定义Xss过滤序列化器/** 间接将html标签去掉@author valarchie */public class JsonHtmlXssTrimSerializer extends JsonDeserializer<String> { public JsonHtmlXssTrimSerializer() { super();}@Overridepublic String deserialize(JsonParser p, DeserializationContext context) throws IOException { String value = p.getValueAsString(); if( value != null) { // 去除掉html标签 如果想要本义的话 可应用 HtmlUtil.escape() return HtmlUtil.cleanHtmlTag(value); } return null;}@Overridepublic Class<String> handledType() { return String.class;}}复制代码配置自定义Xss过滤序列化器@Configurationpublic class JacksonConfig implements Jackson2ObjectMapperBuilderCustomizer{ @Overridepublic void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) { // 防XSS脚本注入 jacksonObjectMapperBuilder.deserializers(new JsonHtmlXssTrimSerializer());}}复制代码如何反对富文本某一些字段可能是须要反对富文本的,比方公告栏里的内容之类的。此时咱们能够给特定的字段标注规范的JsonDeserializer来笼罩咱们自定义的序列化器。 以下是例子。/** @author valarchie */@Datapublic class NoticeAddCommand { /** * 想要反对富文本的话, 防止Xss过滤的话, 请加上@JsonDeserialize(using = StringDeserializer.class) 注解 */@NotBlank@JsonDeserialize(using = StringDeserializer.class)protected String noticeContent;protected String status;}复制代码这是笔者对于Xss的全局对立解决的实现,如有有余欢送大家评论斧正。 ...

April 7, 2023 · 1 min · jiezi

关于fastapi:线上cpu报警的一次接口优化

前言春天到了大地都复苏了,寂静了很久的cpu也开始缓缓复苏了,所谓前人埋坑前人填坑,随同着阿里云监控报警,线上CPU使用率暴增,于是就开始了排查之路。 呈现问题景象因为服务的cpu暴增达到肯定水平,导致服务假死,接口调用全副返回502不可用,链接超时导致服务器方面无奈给予失常的反馈。 通过查看阿里云数据库RDS,慢sql日志进行剖析,发现数据库的CPU使用率在某一时间达到了96%,这不完犊子了。 导出监控平台剖析的慢sql,看到这个sql均匀的执行工夫,真的是再次刷新了我的认知,均匀执行法工夫2分多钟,这怕是执行的黄花菜都要凉了。 问题排查首先依据阿里云剖析的慢sql进行再次剖析,sql必定是有问题的,而导致服务不可用的起因还须要看微服务的负载配置,于是我去查看了该服务Nacos的配置。这里咱们看到该服务Ribbon超时工夫为15妙,就意味着接口如果执行超过这个工夫接口就无奈继续执行,从而呈现服务假死不可用的景象。服务接口调用长时间没有反馈,ribbon负载平衡会触发熔断机制,对服务进行爱护,让服务不可调用。 波及接口通过慢sql对应到问题接口,对接口逻辑进行梳理,排查接口波及到的sql。通过对业务逻辑剖析,发现这个接口对慢sql执行了两次,一次是失常分页查问数据,第二次是没有加分页参数,那么将全表查问,对查问的后果依据字段进行过滤,过滤出count条数。 其次是发现前端对这个接口进行两次调用,咱也不晓得为什么,然而在申请上看来,拜访该页面同一接口的确进行两次调用,原本接口就很慢了,这几乎就是一个暴击。 慢sql剖析因为动静sql比拟长,我只筛选我认为sql不是很适合的中央 查问列中用select嵌套查问 sql中呈现大量字段in的查问In是走索引的查问,然而当in括号外面的条件比拟多的状况下,就是传入的参数这个list列表长度比拟大的状况下,是不走索引的,会进行全表扫描,in最终走不走索引其实是跟前面的数据有关系的。 表中数据量主表大略在25w多数据,关联表比拟大在170w数据。主表索引加了很多,未必就是一件坏事,索引的设置齐全依照搜寻条件来设置也未必对,波及到关联表肯定要增加索引。 关联表呈现了很多反复数据,因为不理解之前业务的逻辑,不太分明为什么呈现很多反复数据,这也是表中数据量很大的起因,从而导致影响查问效率。接口优化既然当初问题找到了,就能够进行优化了,我说下我优化的思路,次要是从下往上进行优化。 慢sql优化,次要是针对嵌套查问改为left join 左外联查问,缩小了in查问,查问进去的数据在代码中进行筛选,缩小了一些不必要的索引。 通过conut()统计须要的条数,在所有count外面,count()是效率最高的了,有趣味的敌人能够去理解下。 业务代码方面,限度了工夫筛选的区间,从原来的不限工夫勾选范畴,跟业务进行沟通后,调整为只容许抉择一周的工夫范畴进行查问,前后端都进行限度。 优化后果比照由此可见优化后的执行效率还是比拟高的,线上服务也没有在报警了,然而还有其余服务在报警…. 还有磁盘使用率达到90%…. Wtf真的是优化之道路漫漫啊。 总结此次对于接口的优化点还不是很深,次要点是对代码、sql、业务进行优化,还未波及到分表、退出缓存热点数据进行预热、批改负载平衡超时工夫等…其实偶然的填坑也是一种学习的形式,不说了持续填坑了,哦!不对优化代码了~

April 7, 2023 · 1 min · jiezi

关于fastapi:公司的这种打包启动方式我简直惊呆了

前言 如果本文对你有帮忙的话,球球帮忙投个票吧,投票通道 感激不尽呀~~ 大家都晓得,SpringBoot利用最终会打出一个Fat Jar, 外面蕴含了用到的全副依赖,启动也非常简单,java -jar xxx.jar即可。 然而咱们公司打出的最终包,将依赖包挪到了内部,而后启动的时候通过loader.path指定依赖包的地位,如java -Dloader.path=libs -jar xxxx的形式启动,也可能启动胜利。 这样做最大的一个益处就是如果发现某个依赖呈现问题,那么我只须要在libs替换其中某个依赖,影响范畴能够减小很多。那大家是不是很好奇是怎么做到的呢?打包形式详解次要是通过两个maven插件打出这样的构造的包。 spring-boot-maven-plugin 该插件是spring boot官网提供的一个打包插件,次要用来打出fat jar,并且提供了反对java -jar xxx.jar形式启动。 官网地址:docs.spring.io/spring-boot…。咱们须要用这个插件,因为只有它能够打出反对启动的jar,然而打出的包中又不能有依赖,该怎么做呢?如下图: layout: 布局形式,这里要抉择ZIP,前面阐明起因。includes: 抉择蕴含哪些依赖,这里写了一个不存在的jar,那么也间接实现了不打入其余的依赖。这种形式比拟ugly,然而目前没有找到更加适合的计划。 maven-assembly-plugin maven-assembly-plugin插件能够灵便定制打包内容,官网地址:maven.apache.org/plugins/mav…。咱们当初就是想方法利用该插件抽出咱们用到的依赖包,该怎么做呢? 咱们当初看下assembly.xml中的要害配置: 能够依据include、exclude属性通过正则灵便的抽取相干依赖到指定的目录下 最终执行mvn clean package在target目录下失去最终的安装包: 解压该安装包: 关上libs目录: 启动形式解析当初咱们曾经依照本人想要的构造打出包了,那如何在启动的时候加载libs目录中的依赖呢?后面提到了springboot插件打出的包是启动的入口,实际上在这个包外面springboot会主动打入一个疏导类org.springframework.boot.loader.Launcher,它是 Spring Boot 可执行 jar 的次要入口点,它是 Spring Boot jar 文件中的理论 Main-Class,用于设置适当的 URLClassLoader 并最终调用 Spring Boot我的项目中定义的 main()办法。Launcher有三个子类(JarLauncher、WarLauncher 和 PropertiesLauncher),如果咱们打包插件的layout配置的是ZIP的形式,它会应用PropertiesLauncher。PropertiesLauncher机制阐明:默认状况下,PropertiesLauncher 在 BOOT-INF/lib/ 中加载,咱们能够通过设置loader.properties 中的loader.path 或 LOADER_PATH 环境变量来减少其它的加载地位。 loader.path:配置逗号分隔的 Classpath 类门路,例如 lib,${HOME}/app/lib,后面的门路优先,相似于 javac 命令中的 -classpath。loader.home:用于解析 loader.path 配置的相对路径,默认是${user.dir}。 ...

March 13, 2023 · 1 min · jiezi

关于fastapi:Guava中这些Map的骚操作让我的代码量减少了50

Guava是google公司开发的一款Java类库扩大工具包,内含了丰盛的API,涵盖了汇合、缓存、并发、I/O等多个方面。应用这些API一方面能够简化咱们代码,使代码更为优雅,另一方面它补充了很多jdk中没有的性能,能让咱们开发中更为高效。明天Hydra要给大家分享的就是Guava中封装的一些对于Map的骚操作,在应用了这些性能后,不得不说一句真香。先引入依赖坐标,而后开始咱们的正式体验吧~<dependency> <groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.1.1-jre</version></dependency>复制代码Table - 双键Mapjava中的Map只容许有一个key和一个value存在,然而guava中的Table容许一个value存在两个key。Table中的两个key别离被称为rowKey和columnKey,也就是行和列。(然而个人感觉将它们了解为行和列并不是很精确,看作两列的话可能会更加适合一些)举一个简略的例子,如果要记录员工每个月工作的天数。用java中一般的Map实现的话就须要两层嵌套:Map<String,Map<String,Integer>> map=new HashMap<>();//寄存元素Map<String,Integer> workMap=new HashMap<>();workMap.put("Jan",20);workMap.put("Feb",28);map.put("Hydra",workMap); //取出元素Integer dayCount = map.get("Hydra").get("Jan");复制代码如果应用Table的话就很简略了,看一看简化后的代码:Table<String,String,Integer> table= HashBasedTable.create();//寄存元素table.put("Hydra", "Jan", 20);table.put("Hydra", "Feb", 28); table.put("Trunks", "Jan", 28);table.put("Trunks", "Feb", 16); //取出元素Integer dayCount = table.get("Hydra", "Feb");复制代码咱们不须要再构建简单的双层Map,间接一层搞定。除了元素的存取外,上面再看看其余的实用操作。1、取得key或value的汇合//rowKey或columnKey的汇合Set<String> rowKeys = table.rowKeySet();Set<String> columnKeys = table.columnKeySet(); //value汇合Collection<Integer> values = table.values();复制代码别离打印它们的后果,key的汇合是不蕴含反复元素的,value汇合则蕴含了所有元素并没有去重:[Hydra, Trunks][Jan, Feb][20, 28, 28, 16]复制代码2、计算key对应的所有value的和以统计所有rowKey对应的value之和为例:for (String key : table.rowKeySet()) { Set<Map.Entry<String, Integer>> rows = table.row(key).entrySet();int total = 0;for (Map.Entry<String, Integer> row : rows) { total += row.getValue();}System.out.println(key + ": " + total);}复制代码打印后果:Hydra: 48Trunks: 44复制代码3、转换rowKey和columnKey这一操作也能够了解为行和列的转置,间接调用Tables的静态方法transpose:Table<String, String, Integer> table2 = Tables.transpose(table);Set<Table.Cell<String, String, Integer>> cells = table2.cellSet();cells.forEach(cell-> ...

January 9, 2023 · 2 min · jiezi

关于fastapi:Netty-概述

1、什么是 NettyNetty is an asynchronous event-driven network application frameworkfor rapid development of maintainable high performance protocol servers & clients.复制代码Netty 是一个异步的、基于事件驱动的网络应用框架,用于疾速开发可保护、高性能的网络服务器和客户端 留神:netty的异步还是基于多路复用的,并没有实现真正意义上的异步IO 2、Netty 的劣势如果应用传统 NIO,其工作量大,bug 多 须要本人构建协定解决 TCP 传输问题,如粘包、半包因为 bug 的存在,epoll 空轮询导致 CPU 100% Netty 对 API 进行加强,使之更易用,如 FastThreadLocal => ThreadLocalByteBuf => ByteBuffer 3、入门案例1、服务器端代码public class HelloServer { public static void main(String[] args) { // 1、启动器,负责拆卸netty组件,启动服务器 new ServerBootstrap() // 2、创立 NioEventLoopGroup,能够简略了解为 线程池 + Selector .group(new NioEventLoopGroup()) // 3、抉择服务器的 ServerSocketChannel 实现 .channel(NioServerSocketChannel.class) // 4、child 负责解决读写,该办法决定了 child 执行哪些操作 // ChannelInitializer 处理器(仅执行一次) // 它的作用是待客户端 SocketChannel 建设连贯后,执行 initChannel 以便增加更多的处理器 .childHandler(new ChannelInitializer<NioSocketChannel>() { @Override protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception { // 5、SocketChannel的处理器,应用StringDecoder解码,ByteBuf=>String nioSocketChannel.pipeline().addLast(new StringDecoder()); // 6、SocketChannel的业务解决,应用上一个处理器的处理结果 nioSocketChannel.pipeline().addLast(new SimpleChannelInboundHandler<String>() { @Override protected void channelRead0(ChannelHandlerContext channelHandlerContext, String s) throws Exception { System.out.println(s); } }); } // 7、ServerSocketChannel绑定8080端口 }).bind(8080);}}复制代码2、客户端代码public class HelloClient { ...

December 28, 2022 · 2 min · jiezi