关于网站安全性的相关优化

1.网站涉及相应文件的上传

①考虑文件的大小

/**
     * 校验文件大小是否合法
     * 此处文件大小是否合法的临界值是 ONE_MB
     * @param multipartFile
     * @return
     */
    public boolean isSizeLegal(MultipartFile multipartFile){
        final long ONE_MB = 1024 * 1024L;
        long size = multipartFile.getSize();
        if (size > ONE_MB){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"文件过大");
        }
        return true;
    }

②考虑文件是否合法(后缀名是否符合要求)

/**
     * 校验后缀名是否合法
     * @param multipartFile
     * @return
     */
    public boolean isSuffixLegal(MultipartFile multipartFile){
        String originalFilename = multipartFile.getOriginalFilename();
        //调用huTool工具类的getSuffix()获取文件的后缀名
        String suffixName = FileUtil.getSuffix(originalFilename);
        //新建合法后缀名的白名单
        final List<String> validFileSuffixList = Arrays.asList("jpg","png","svg","webp","jpeg","xlsx");
        if (!validFileSuffixList.contains(suffixName)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"文件后缀名不合法");
        }
        return true;
     }

③考虑文件的内容

④考虑文件的合规性(是否包含敏感信息)

可以接入腾讯云的图片万象数据审核

2.数据存储及查询

业务分析:现在有一个图表信息表,里面存储的相关字段如下,如果每一个用户上传的“图表数据”100M(不超过规定的大小),那么该chart表的查询速度则会大大降低

create table chart
(
    id         bigint auto_increment comment 'id'
        primary key,
    goal       text                               null comment '分析目标',
    chartData  text                               null comment '图表数据',
    chartType  varchar(128)                       null comment '图表类型',
    genChart   text                               null comment '生成的图表数据',
    genResult  text                               null comment '生成的分析结果',
    userId     bigint                             null comment '创建用户 id',
    createTime datetime default CURRENT_TIMESTAMP not null comment '创建时间',
    updateTime datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
    isDelete   tinyint  default 0                 not null comment '是否删除',
    name       varchar(128)                       null comment '图表名称'
)
    comment '图表信息表' collate = utf8mb4_unicode_ci;

用户现在只需要查询chart表的“图表数据”进行简单查询,即保存文件的原始数据有什么优化方法?

解决方法:分库分表

把每一个图表对应的原始数据单独保存作为一个新的数据表,而不是都存放在一个字段中

示例:

比如现在要保存 “网站数据.xlsx”,那么我们就新建一个数据表,表名 chart_{图表id},表内字段和“网站数据.xlsx”内字段一一对应并存储相同数据

2.1数据存储

ChartMapper.xml

    <insert id="createChartData" parameterType="string">
        ${InsertSql}
    </insert>

ChartMapper接口

声明方法

void createChartData(String insertSql);

测试

    @Test
    void createChartData() {
        String chartId = "1705232019000590337";
        String columns_one = "日期";
        String columns_two = "人数";
        String InsertSql = String.format("create table chart_%s (%s varchar(128),%s 
              int(10))",chartId,columns_one,columns_two);
        chartMapper.createChartData(InsertSql);
        //添加数据......
    }

 结果

新建 chart_1705232019000590337 数据表

 2.2数据查询

前提:数据已存储在相应的数据表

ChartMapper.xml

<select id="queryChartData" parameterType="string" resultType="map">
        ${querySql}
</select>

ChartMapper接口声明对应的方法

List<Map<String,Object>> queryChartData(String querySql);

测试

    @Test
    void queryChartData() {
        String chartID = "1705772545445376001";
        String querySql = String.format("select * from chart_%s",chartID);
        List<Map<String, Object>> maps = chartMapper.queryChartData(querySql);
        System.out.println(maps);
    }

结果

对应的数据表存储内容如下

动态sql获取的数据如下

3.限流

关于限流的四种经典算法:面试必备:4种经典限流算法讲解 - 掘金

 ---使用Redission的RateLimiter

①引入依赖

        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>3.23.5</version>
        </dependency>

②yml配置redis信息---实现动态读取配置

spring: 
 redis:
    database: xxx
    host: xxx
    port: xxx
    timeout: xxx
    password:xxx

③新建redis配置类---@Bean注解

@Bean是用在方法上,将当前方法的返回值对象放到ioc容器当中!

但是只有方法上有@Bean是无法将对象放入容器当中的,该@Bean修饰的方法应该在@controller、@Service、@Component、@Configuration、@Repository修饰的类当中才可以!

@Configuration
@ConfigurationProperties("spring.redis")

注解作用:可以将properties/yml配置文件中的内容读取并封装到JavaBean中(字段名相同)

/**
 *redis配置类
 *
 */
@Configuration
@ConfigurationProperties("spring.redis")
@Data
public class RedisConfig {
    Integer database;
    String host;
    Integer port;
    @Bean
    public RedissonClient getRedissonClient(){
        // 1. Create config object
        Config config = new Config();
        config.useSingleServer()
                .setDatabase(database)
                .setAddress("redis://" + host + ":" + port);
        //2.创建实例
        RedissonClient redisson = Redisson.create(config);
        return redisson;
    }
}

④RedisLimiterManager

Manager包---通用的中间组件层

trySetRate()方法的四个参数:

boolean trySetRate(RateType mode, long rate, long rateInterval, RateIntervalUnit rateIntervalUnit);

mode – - rate mode 限流类型
rate – - rate 限流速率/速度
rateInterval – - rate time interval 限流的时间间隔
rateIntervalUnit – - rate time interval unit 速率时间间隔单位

tryAcquire():每次请求的令牌数

@Service
public class RedisLimiterManager {

    @Resource
    private RedissonClient redissonClient;

    /**
     * 限流器
     * @param key 区分不同的限流器,比如用户的id应该分别统计
     */
    public void doRateLimiter(String key){
        RRateLimiter rateLimiter = redissonClient.getRateLimiter(key);
        //设置限流器的规则
        rateLimiter.trySetRate(RateType.OVERALL,2,1, RateIntervalUnit.SECONDS);
        //每当来操作,请求令牌 permits(每次获得许可证的数量)
        boolean canOP = rateLimiter.tryAcquire(1);
        if (!canOP){
            throw new BusinessException(ErrorCode.TOO_MANY_REQUEST,"请求过于频繁");
        }
    }
}

⑤具体应用

注意:限流器 doRateLimiter(String key)Key参数的设置!

        //判断限流
        String key = "genChartByAi_" + loginUser.getId();
        redisLimiterManager.doRateLimiter(key);

此处的key是具体的方法名+用户的id组合的 字符串

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值