美团面试:接口被恶意狂刷,怎么办?

如果Java接口被恶意狂刷,我们一般可以采取以下措施:

用TimeStamp (兵不厌诈)

比如给客户端提供一个timestamp参数,值是13位的毫秒级时间戳,可以在第12位或者13位做一个校验位,通过一定的算法给其他12位的值做一个校验。

举例:现在实际时间是 1684059940123,我通过前12位算出来校验位是9,参数则把最后一位改成9,即1684059940129,值传到服务端后通过前十二位也可以算出来值,来判断这个时间戳是不是合法的。

根据前面12位计算校验位,可以使用以下代码实现:

/**
 * 计算timestamp的校验位
 */
private int calculateCheckDigit(long timestamp) {
    int sum = 0;
    for (int i = 0; i < TIMESTAMP_DIGITS - 1; i++) {
        char c = String.valueOf(timestamp).charAt(i);
        sum += Integer.parseInt(String.valueOf(c));
    }
    return sum % 10;
}

在上述代码中,calculateCheckDigit方法接收一个13位毫秒级时间戳作为参数,返回该时间戳的校验位。具体地,该方法会循环遍历时间戳的前12位,并将这些数字相加。最后,计算总和的个位数并返回。

例如:如果时间戳为1684059940123,则该方法计算出来的校验位为9。

但是如果黑客翻客户端代码,就知道校验位的情况了。因为这个校验逻辑客户端必然也有一份。如果客户端代码是公开的,那么攻击者可以通过研究客户端代码得到校验位计算的方式。这样一来,攻击者就有可能伪造出带有正确校验位的timestamp参数,从而绕过Java接口的限流和安全机制。

因此,该方案主要适用于需要简单防范一些低强度攻击的场景,例如防范垃圾请求或非法爬虫等。对于高强度攻击,建议采取更为复杂的验证策略,例如使用OAuth2授权、IP白名单、签名算法等。同时,建议客户端和服务端在通信过程中使用HTTPS协议进行加密,防止数据被窃听或篡改。

加强安全认证

@RequestMapping("/api/login")
public String login(@RequestParam("username") String username, @RequestParam("password") String password){
    if(!checkUser(username, password)){
        return "用户名或密码错误";
    }
    String token = getToken();
    saveToken(token);
    return token;
}

private boolean checkUser(String username, String password){
    //校验用户是否合法
}

private String getToken(){
    //生成token
}

private void saveToken(String token){
    //保存token
}

在上述代码中,当用户调用login接口时,需要提供用户名和密码。此时会进行用户校验,若校验失败则返回错误信息,否则生成token并保存,最终返回给用户。

生成Token的作用是为了在接口请求时验证用户身份。具体来说,当用户第一次登录系统后,该接口可以根据用户信息生成一个Token字符串,并将其保存至服务端或客户端。当此用户访问其他需要鉴权的接口时,需要在请求头中带上这个Token字符串,以便服务器进行身份验证。

对于Java接口被恶意狂刷问题,Token的作用是防止非法请求。由于Token是由服务端生成的,攻击方无法自己生成有效的Token,因此只有拥有合法Token的用户才能成功调用相关接口。

关于Token的验证,可以通过拦截器实现。拦截器可以在接口调用前检查请求头中是否包含合法的Token,并验证Token是否过期、是否被篡改等。如果Token验证失败,则返回错误信息并拦截该请求。

下面是生成Token和使用拦截器的示例代码:

// 生成Token
private String generateToken(User user) {
    // 基于用户名、密码、时间戳等信息生成Token字符串
}

// 鉴权拦截器
public class AuthInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler) throws Exception {
        String token = request.getHeader("Authorization");
        if (token == null || !checkToken(token)) {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            return false;
        }
        return true;
    }

    private boolean checkToken(String token) {
        // 验证Token是否合法,是否过期等
    }
}

在上述代码中,generateToken方法用于生成Token字符串,并保存至服务端或客户端。AuthInterceptor类是拦截器类,用于检查请求头中的Token是否合法。如果Token验证失败,则返回401错误码并拦截该请求。需要注意的是,在使用该拦截器时,需要将其注册到Spring MVC框架中。

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Autowired
    private AuthInterceptor authInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authInterceptor).addPathPatterns("/api/**");
    }
}

以上代码是将AuthInterceptor拦截器注册到Spring MVC框架中,使其生效。其中,"/api/**"表示拦截所有以"/api"开头的接口。

IP封禁

public class IpFilter extends OncePerRequestFilter {
    private static final Set<String> IP_SET = new HashSet<>();

    static {
        IP_SET.add("192.168.1.100");
        IP_SET.add("127.0.0.1");
        //添加其他需要封禁的IP
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
        String ipAddress = request.getRemoteAddr();
        if(IP_SET.contains(ipAddress)){
            response.setStatus(HttpStatus.FORBIDDEN.value());
            return;
        }

        filterChain.doFilter(request, response);
    }
}

在上述代码中,通过IpFilter过滤器来阻止特定的IP地址访问接口。其中,IP_SET为需要封禁的IP地址集合。

接口限流

public class RateLimitInterceptor extends HandlerInterceptorAdapter {
    private static final int DEFAULT_RATE_LIMIT_COUNT = 100; //默认每秒允许100次请求
    private static final int DEFAULT_RATE_LIMIT_TIME_WINDOW = 1000; //默认时间窗口为1秒
    private Map<String, Long> requestCountMap = new ConcurrentHashMap<>();
    private int rateLimitTimeWindow;
    private int rateLimitCount;

    public RateLimitInterceptor(){
        this(DEFAULT_RATE_LIMIT_TIME_WINDOW, DEFAULT_RATE_LIMIT_COUNT);
    }

    public RateLimitInterceptor(int timeWindow, int limitCount){
        this.rateLimitTimeWindow = timeWindow;
        this.rateLimitCount = limitCount;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        String key = request.getRemoteAddr() + ":" + request.getRequestURI();
        long now = System.currentTimeMillis();
        if(requestCountMap.containsKey(key)){
            long last = requestCountMap.get(key);
            if(now - last < rateLimitTimeWindow){
                if(requestCountMap.get(key) >= rateLimitCount){
                    response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
                    return false;
                }
                requestCountMap.put(key, requestCountMap.get(key) + 1);
            }else{
                requestCountMap.put(key, now);
            }
        }else{
            requestCountMap.put(key, now);
        }
        return true;
    }
}

在上述代码中,通过RateLimitInterceptor拦截器实现接口限流功能。默认情况下,每秒钟最多允许100次请求。如果当秒内请求数超过限制,则返回状态码429。

日志监控

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    throws IOException, ServletException {
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response;
    String requestURI = httpRequest.getRequestURI();

    try {
        log.info("Request Received. URI: {}", requestURI);
        chain.doFilter(request, response);
    } catch(Exception e) {
        log.error("Exception occurred while processing request. URI: {}", requestURI, e);
        throw e;
    } finally {
        log.info("Request Completed. URI: {} Response Status: {}", requestURI, httpResponse.getStatus());
    }
}

在上述代码中,通过Filter过滤器来实现日志监控。当请求进入时记录请求URI,当请求结束时记录响应状态码,如此可及时发现异常情况。

升级硬件设备

如果服务器无法承受恶意攻击,可以通过升级硬件设备来增加服务器的承载能力。例如,可以增加CPU或内存等硬件资源,降低服务器的响应时间。

通知相关部门

当Java接口被恶意狂刷时,及时通知相关管理人员或安全团队是非常重要的。他们可以采取更加有效的措施,如封禁IP地址、加强认证机制等,从而保障接口的安全。以下是一些示例代码:

//发送邮件通知相关部门
public void sendNotificationEmail(String subject, String content, String... recipients) {
    SimpleMailMessage message = new SimpleMailMessage();
    message.setFrom("sender@example.com");
    message.setTo(recipients);
    message.setSubject(subject);
    message.setText(content);
    
    mailSender.send(message);
}

//发送短信通知相关部门
public void sendNotificationSMS(String phoneNumber, String content) {
    //调用第三方短信API发送短信
}

总结

1.大部分情况,token校验+拦截器已然足够,敏感接口再加限流,这也是大部分企业的做法。

2.简单场景用TimeStamp就行了,对于大部分机器人恶意访问,他是不可能去看你代码的。

3.尽量不要封禁IP,防止误伤,因为很多小区住户往往是局域网,很多人就是共用一个IP的。

4.更狠的方法是,模仿那种”请选择图片中的汽车“的做法,反向薅羊毛,嗯,大家应该明白其中的意思。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/23991.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

中国人民大学与加拿大女王大学金融硕士——每天都要优于过去的自己,加油!

职场中拉开人与人之间差距的&#xff0c;往往是日复一日微小的积累。满足已取得的成就会让人停滞不前&#xff0c;一旦停止学习&#xff0c;人就会止步不前。懂得持续学习、终生成长的人&#xff0c;能保持积极进取的状态。金融行业的你有计划来人民大学与加拿大女王大学金融硕…

Redis之高可用方案浅析

在工程项目中&#xff0c;系统应用的高可用性越来越重要&#xff0c;业主越来越重视。其实高可用可以分为应用层高可用和数据层高可用&#xff0c;数据层高可用中常见的有关系型数据库mysql的高可用、非关系型NoSQl数据库redis的高可用等&#xff0c;下面聊聊典型的NoSQL数据库…

深入理解Linux虚拟内存管理

系列文章目录 Linux 内核设计与实现 深入理解 Linux 内核&#xff08;一&#xff09; 深入理解 Linux 内核&#xff08;二&#xff09; Linux 设备驱动程序&#xff08;一&#xff09; Linux 设备驱动程序&#xff08;二&#xff09; Linux 设备驱动程序&#xff08;三&#xf…

yolov5-7.0 添加BiFPN

1. BiFPN特征融合 BiFPN是目标检测中神经网络架构设计的选择之一&#xff0c;为了优化目标检测性能而提出。主要用来进行多尺度特征融合&#xff0c;对神经网络性能进行优化。来自EfficientDet: Scalable and Efficient Object Detection这篇论文。 在这篇论文中&#xff0c;作…

Linux的学习

学习笔记&#xff0c;只写重点&#xff0c;不连贯&#xff0c;写得很水。 视频from:2021韩顺平 一周学会Linux。学习地址&#xff1a;https://www.bilibili.com/video/BV1Sv411r7vd 老师说明&#xff1a;后面我们的Redis、ginx包括项目都会使用到Linux,也是和我讲解的Linux版本…

Seata AT模式源码解析二(Seata Client端启动流程)

文章目录 初始化TM和RM数据源代理 由于我们一般都是在springboot中使用的&#xff0c;而与springboot集成的我们一般就先看starter的spring.factories文件&#xff0c;看看它的自动装配 这里面主要关注SeataAutoConfiguration和SeataDataSourceAutoConfiguration。 SeataAutoCo…

破解极域(4):万能密码法(可以获取到原密码)

破解极域&#xff08;4&#xff09;&#xff1a;万能密码法 1.思路2.实现2.1 获得密码2.2 解除控制2.3 特别注意 3.视频展示 今天来分享下破解极域的第4种方法——万能密码法 1.思路 首先&#xff0c;我们要知道的是&#xff0c;极域这个东西它有一个万能密码&#xff0c;万能…

如何检查Linux硬盘大小、类型和硬件详细信息?

在Linux系统中&#xff0c;了解硬盘的大小、类型和硬件详细信息对于系统管理和故障排除非常重要。本文将详细介绍如何使用命令行工具来检查Linux硬盘的大小、类型和硬件详细信息。 1. 检查硬盘大小 要检查Linux硬盘的大小&#xff0c;可以使用lsblk命令。该命令显示了系统中所…

我用AI帮我唱了首“基尼太美”,颠覆了我的认知!太牛逼了

目录 前言 AI唱"基尼太美"是什么感觉 使用so-vits-svc打造自己专属歌手 1.声音素材整理 2.训练模型 3.让AI唱歌​编辑 AI歌手背后的技术 AI歌手会成为主流吗 写到最后 大家好&#xff0c;我是大侠&#xff0c;AI领域的专业博主 前言 在5月份&#xff0c;孙…

vue2_模版语法

目录 模版语法 react用jsx语法编译后的null作用 插值表达式{{}} v-bind和{{}} 关于国内谷歌自带翻译停用如何解决&#xff08;额外&#xff09; 会一点的插值表达式&#xff0c;也有限制 模版语法 更接近原生js的写法jsx语法 jsx是react提出的&#xff1b;后很多前端框架…

说说你对slot的理解?slot使用场景有哪些?

vue的slot的理解&#xff1f;slot使用场景有哪些&#xff1f; 定义 在Vue.js中&#xff0c;slot&#xff08;插槽&#xff09;是一种用于组件之间内容分发的机制。它允许你在父组件中编写子组件的内容&#xff0c;从而增加了组件的灵活性和可重用性。 Slot 艺名插槽&#xf…

汇编寄存器之内存访问

1.内存中字的存储: 在CPU中用一个16位寄存器来存储一个字, 高8位存高字节,低8位存低字节 如AX寄存器存在一个字,那么AH存高字节,AL存低字节 在内存中存储字时是用两个连续的字节来存储字的, 这个字的低字节存在低单元,高字节存在高单元. 如下表示: 内存单元编号 单元中…

【微博-计算Cell子控件的frame Objective-C语言】

一、计算Cell子控件的frame 1.来,看一下,刚才我们已经做到把这个模型设置给自定义的cell了吧, 那么,在这个自定义Cell里面呢,我们是不是要开始设置数据了, 设置数据,我们,设置数据,其实很简单,就是把我们这里边的每一个控件,对应的值,从模型里面取出来,给了它,…

【独立版】智慧城市同城V4_2.2.7全开源全插件VUE版,修复房产信息组件商户发布二手房房源信息未和商户关联的问题

源码介绍 【独立版】智慧城市同城V4 查看更多关于 智慧城市同城V4 的文章 _2.2.7全开源全插件VUE版&#xff0c;修复房产信息组件商户发布二手房房源信息未和商户关联的问题&#xff01; 智慧城市同城是一套专注于多城市生活服务同城技术解决方案,全面覆盖同堿信息、商家联盟、…

【Linux】搭建SFTP文件服务器

一、协议介绍1.1 FTP 协议1.11 特点1.12 基本工作原理 1.2 SFTP协议1.21 特点1.22 基本工作原理 1.3 ssh协议1.31 特点1.32 基本工作原理 1.4 其他常见文件传输协议 二、搭建Linux的SFTP文件服务器三、连接测试3.1 电脑连接3.2 手机连接 一、协议介绍 1.1 FTP 协议 1.11 特点…

AI落地:高效学习指南

高效学习中有一个共识&#xff1a;学习最小可用知识&#xff0c;然后立马开始实践&#xff0c;做中学&#xff0c;不断获得反馈&#xff0c;不断在实践中改进。 现实生活中&#xff0c;如果我们想实现这种高效学习&#xff0c;基本上只能找一个老师1对1指导&#xff0c;费用贵…

【开发者指南】如何在MyEclipse中使用 XML编辑器

XML编辑器包括高级XML编辑功能。通过本文&#xff0c;你将了解其编辑功能和网页XML编辑&#xff0c;一起来看看吧~ 1. Web XML编辑器 MyEclipse Web XML编辑器包括高级XML编辑功能&#xff0c;如: 语法高亮显示标签和属性内容辅助实时验证(在您输入时)文档内容的源视图、设计…

160743-62-4,DMG PEG2000,1,2-二肉豆蔻酰-rac-甘油-3-甲氧基聚乙二醇2000

DMG PEG2000&#xff0c;DMG-mPEG2000&#xff0c;1,2-二肉豆蔻酰-rac-甘油-3-甲氧基聚乙二醇2000 Product structure&#xff1a; Product specifications&#xff1a; 1.CAS No&#xff1a;160743-62-4 2.Molecular formula&#xff1a; C34H66O 3.Molecular weight&#xff…

Java内部类(成员内部类、静态嵌套类、方法内部类、匿名内部类)

文章目录 一、内部类的共性二、为什么需要内部类三、静态内部类&#xff08;静态嵌套类&#xff09;四、成员内部类五、局部内部类&#xff08;方法内部类&#xff09;六、匿名内部类 Java 类中不仅可以定义变量和方法&#xff0c;还可以定义类&#xff0c;这样定义在类内部的类…

挂耳式耳机品牌排行榜,看看谁被推荐上榜

下班路上就想放空自己刷会儿视频&#xff0c;但是马路、地铁还有公交上都会有嘈杂的声音影响&#xff0c;如果佩戴入耳式耳机放大声音不仅会过度屏蔽外界&#xff0c;同时还会损伤我们的耳朵&#xff0c;所以新近流行的开放式耳机很好的解决了这些问题&#xff0c;但也有很多小…