Dayu 安全组件

背景
交付场景中安全问题非常重要。基础技术组现在基于spring boot starter,开发了安全二方库,用于解决在生产环境中常见的安全问题。
主要功能
● CSRF防范
● XSS防范
● SQL注入防范
● 路径遍历防范
● 系统命令及参数过滤
● 防止重复提交

代码仓库地址
https://code.dayu.work/dayu-security/dayu-security-all.git

maven依赖

 <dependency>
   <groupId>com.aliyun.gts.bpaas</groupId>
   <artifactId>aliyun-gts-security-spring-boot-starter</artifactId>
   <version>2.1.13.3-SNAPSHOT</version>
</dependency>

如何使用
引入如上依赖后,即可在项目中使用。现在分别介绍如何使用该二方库,针对各个安全漏洞进行代码层面上的编码。

CSRF
CSRF是什么
CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。
CSRF可以做什么
你这可以这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账…造成的问题包括:个人隐私泄露以及财产安全。

CSRF原理
参考文档:https://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html

防范
CSRF主要防范方式是在前端http请求中配置一个能够被服务器验证的token。

配置
在这里插入图片描述

引入二方库以后,返回的cookie中包含名为XSRF-TOKEN的token,请前端从cookie中获取该token,并在请求的header中,带入该token,参数名为X-XSRF-TOKEN否则方法会抛出异常。

XSS
XSS是什么?
XSS漏洞是Web应用程序中最常见的漏洞之一。
XSS是指恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。
参考文档:https://www.jianshu.com/p/4fcb4b411a66

二方库使用
在方法或者Controller类上加入注解XssResponseFilter,返回的对象中String类型的字段会被执行html过滤。
例如如下代码:

@PostMapping("/testFilter")
@XssResponseFilter
public ResultResponse<String> testFilter(@RequestBody RequestDto requestDto) {
   String requestStr = JSON.toJSONString(requestDto);
   ResultResponse<String> r = new ResultResponse<>();
   r.setData(requestStr);
   return r;
}

当前端发送请求内容如下:

{
  "json": "ha"
}

会返回:

{
  "message":"success",
  "data":"{&quot;json&quot;:&quot;ha&quot;}",
}

json字符串被进行了转义。

配置
在这里插入图片描述
防止重复提交(单机版)
使用
我们常常需要防止重复提交,例如多次点击造成订单重复提交,或者造成重复汇款等操作。本组件通过注解配置的方式来实现方法的幂等效果。

例子:

@NoDuplicateSubmission(lockKey = "#id")
public void testMethod(long id) {
}

默认情况下,会自动根据类名、方法名、参数hash值来作为重复提交判断的key。 如果需要自定义缓存key,可通过注解中的参数lockKey来指定(支持spel表达式)。

关于在分布式环境下防止重复提交,请参考缓存中间件(aliyun-gts-middleware-cache-starter)中的分布式锁注解"@GTSDistributedLock"。
配置
在这里插入图片描述
防路径遍历
路径遍历的主要问题是用户通过构造非法的路径请求(例如图片的路径),访问未授权的服务器本地文件地址。这种情况主要是由于没有对用户输入的参数的合法性进行校验。

使用
在Controller方法的参数上加入注解@PathFilter,会对参数执行路径遍历过滤。 需注意加了@PathFilter注解就不需要加@RequestParam注解了,不然会导致自定义注解失效。

例子:

    @GetMapping("/path-traversal/secure/path-filter")
    public ResultResponse<String> getImageSecByPathFilter(@PathFilter String filePath) throws IOException {
        ResultResponse<String> r = new ResultResponse<>();
        r.setData(getImgBase64(filePath));
        return r;
    }

发送请求http://localhost:8080/path-traversal/secure/path-filter?filePath=…/…/…/…/…/…/etc/passwd,会返回报错。

{
    "timestamp": "2021-02-19T05:55:36.736+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": "The path argument cannot contain relative or absolute path",
    "path": "/path-traversal/secure/path-filter"
}

SecurityUtils
包含一系列常用工具方法用于过滤可能包含非法字符的输入。

转义命令行参数
如果你的代码中会运行一个命令行,同时命令行的参数来自用户输入,请使用如下方法来过滤参数本身。

// 输出 'cat /password',带引号
SecurityUtils.escapeShellArg("cat /password")

HTML安全转义函数
对HTML字符串进行转义。

String escaped = SecurityUtils.escapeHtml("<html></html>");
assertEquals("&lt;html&gt;&lt;/html&gt;", escaped);

XML安全转义函数
执行xml 1.1安全转义。

String escaped = SecurityUtils.escapeXml("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
assertEquals("&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;", escaped);

JSON安全转义函数

String escaped = SecurityUtils.escapeJson("{\"name\": \"li\", \"first name\": \"chen\"}");
assertEquals("\\u007B\\\"name\\\"\\u003A\\u0020\\\"li\\\"\\u002C\\u0020\\\"first\\u0020name\\\"\\u003A\\u0020"
            + "\\\"chen\\\"\\u007D", escaped);

下面是SQL拼接时候推荐使用的方法。如果使用mybatis,使用 # 替代 $

List<User> users = userMapper.findByUserNameSecure2(SecurityUtils.escapeSql(keyword));

SQL order by参数过滤函数

List<User> users = userMapper.findOrderByVulnerable3(SecurityUtils.escapeSql(orderBy));

防篡改和重放
前端组件使用方法
具体请查看:https://dayu.work/devops/materiel/fe/componentDetail/3257
配置项
在这里插入图片描述
使用
1.需要将gts.security.sign-check.enable的值设置为true
2.需要实现缓存接口cacheInterface

public interface CacheInterface {

    /**
     * 判断缓存中是否拥有此值
     * @param key 键
     * @return 是否拥有
     */
    boolean hasKey(String key);

    /**
     * 写入缓存
     * @param key  键
     * @param value 值
     * @param timeToLive 存在时常
     * @param timeUnit 时间单位
     */
    void setKey(String key, String value, long timeToLive, TimeUnit timeUnit);
}

推荐使用中间件中的缓存组件实现,具体内容参考
https://iwhale-citybrain.yuque.com/altet6/dl2a5i/vfqn74

实现example

@Service
public class CacheService implements CacheInterface {

    @Autowired
    CacheManager cacheManager;

    @Override
    public boolean hasKey(String key) {
        return cacheManager.hasKey(key);
    }

    @Override
    public void setKey(String key, String value, long timeToLive, TimeUnit timeUnit) {
        cacheManager.set(key,value,timeToLive,timeUnit);
    }
}

此实现类需要使用@Service或者@Component来注入
在开启防篡改和重放后,如果未实现cacheInterface或者该实现类未注入将启动报错
在这里插入图片描述
3.签名加解密方式
gts.security.sign-check.signMethod的值需要与前端约定保持一致,否则将数字签名失败

校验步骤
a. 前端发送两个header,一个是gts-ca-timestamp,获取当前发送时间;一个是gts-ca-nonce,一般是md5(timestamp + random()或者一个uuid)。

b. 后端收到timestamp以后,判断和当前系统时间的差距,如果过大,认为超时。

c. 检查nouce,如果在分布式cache中不存在,放在分布式cache中,expire时间为timestamp。如果存在,认为是重复提交。

错误说明
a.参数校验
header中未包含签名gts-ca-signature
返回

{
    "message": "签名不允许为空",
    "success": false
}

header中未包含签名gts-ca-timestamp
返回

{
    "message": "时间戳不允许为空",
    "success": false
}

header中未包含签名gts-ca-nonce
返回

{
    "message": "客户端随机值不可为空",
    "success": false
}

b.过期校验
返回

{
    "message": "已过期的签名",
    "success": false
}

c.重放校验
返回

{
    "message": "重复请求",
    "success": false
}

d.安全签名校验
返回

{
    "message": "数字签名失败",
    "success": false
}

试用地址
http://dayu-sign-check-demo-daily.ingress.dayu.work/home

热门文章

暂无图片
编程学习 ·

gdb调试c/c++程序使用说明【简明版】

启动命令含参数&#xff1a; gdb --args /home/build/***.exe --zoom 1.3 Tacotron2.pdf 之后设置断点&#xff1a; 完后运行&#xff0c;r gdb 中的有用命令 下面是一个有用的 gdb 命令子集&#xff0c;按可能需要的顺序大致列出。 第一列给出了命令&#xff0c;可选字符括…
暂无图片
编程学习 ·

高斯分布的性质(代码)

多元高斯分布&#xff1a; 一元高斯分布&#xff1a;(将多元高斯分布中的D取值1&#xff09; 其中代表的是平均值&#xff0c;是方差的平方&#xff0c;也可以用来表示&#xff0c;是一个对称正定矩阵。 --------------------------------------------------------------------…
暂无图片
编程学习 ·

强大的搜索开源框架Elastic Search介绍

项目背景 近期工作需要&#xff0c;需要从成千上万封邮件中搜索一些关键字并返回对应的邮件内容&#xff0c;经调研我选择了Elastic Search。 Elastic Search简介 Elasticsearch &#xff0c;简称ES 。是一个全文搜索服务器&#xff0c;也可以作为NoSQL 数据库&#xff0c;存…
暂无图片
编程学习 ·

Java基础知识(十三)(面向对象--4)

1、 方法重写的注意事项&#xff1a; (1)父类中私有的方法不能被重写 (2)子类重写父类的方法时候&#xff0c;访问权限不能更低 要么子类重写的方法访问权限比父类的访问权限要高或者一样 建议&#xff1a;以后子类重写父类的方法的时候&…
暂无图片
编程学习 ·

Java并发编程之synchronized知识整理

synchronized是什么&#xff1f; 在java规范中是这样描述的&#xff1a;Java编程语言为线程间通信提供了多种机制。这些方法中最基本的是使用监视器实现的同步(Synchronized)。Java中的每个对象都是与监视器关联&#xff0c;线程可以锁定或解锁该监视器。一个线程一次只能锁住…
暂无图片
编程学习 ·

计算机实战项目、毕业设计、课程设计之 [含论文+辩论PPT+源码等]小程序食堂订餐点餐项目+后台管理|前后分离VUE[包运行成功

《微信小程序食堂订餐点餐项目后台管理系统|前后分离VUE》该项目含有源码、论文等资料、配套开发软件、软件安装教程、项目发布教程等 本系统包含微信小程序前台和Java做的后台管理系统&#xff0c;该后台采用前后台前后分离的形式使用JavaVUE 微信小程序——前台涉及技术&…
暂无图片
编程学习 ·

SpringSecurity 原理笔记

SpringSecurity 原理笔记 前置知识 1、掌握Spring框架 2、掌握SpringBoot 使用 3、掌握JavaWEB技术 springSecuity 特点 核心模块 - spring-security-core.jar 包含核心的验证和访问控制类和接口&#xff0c;远程支持和基本的配置API。任何使用Spring Security的应用程序都…
暂无图片
编程学习 ·

[含lw+源码等]微信小程序校园辩论管理平台+后台管理系统[包运行成功]Java毕业设计计算机毕设

项目功能简介: 《微信小程序校园辩论管理平台后台管理系统》该项目含有源码、论文等资料、配套开发软件、软件安装教程、项目发布教程等 本系统包含微信小程序做的辩论管理前台和Java做的后台管理系统&#xff1a; 微信小程序——辩论管理前台涉及技术&#xff1a;WXML 和 WXS…
暂无图片
编程学习 ·

如何做更好的问答

CSDN有问答功能&#xff0c;出了大概一年了。 程序员们在编程时遇到不会的问题&#xff0c;又没有老师可以提问&#xff0c;就会寻求论坛的帮助。以前的CSDN论坛就是这样的地方。还有技术QQ群。还有在问题相关的博客下方留言的做法&#xff0c;但是不一定得到回复&#xff0c;…
暂无图片
编程学习 ·

矩阵取数游戏题解(区间dp)

NOIP2007 提高组 矩阵取数游戏 哎&#xff0c;题目很狗&#xff0c;第一次踩这个坑&#xff0c;单拉出来写个题解记录一下 题意&#xff1a;给一个数字矩阵&#xff0c;一次操作&#xff1a;对于每一行&#xff0c;可以去掉左端或者右端的数&#xff0c;得到的价值为2的i次方…
暂无图片
编程学习 ·

【C++初阶学习】C++模板进阶

【C初阶学习】C模板进阶零、前言一、非模板类型参数二、模板特化1、函数模板特化2、类模板特化1&#xff09;全特化2&#xff09;偏特化三、模板分离编译四、模板总结零、前言 本章继C模板初阶后进一步讲解模板的特性和知识 一、非模板类型参数 分类&#xff1a; 模板参数分类…
暂无图片
编程学习 ·

字符串中的单词数

统计字符串中的单词个数&#xff0c;这里的单词指的是连续的不是空格的字符。 input: "Hello, my name is John" output: 5 class Solution {public int countSegments(String s) {int count 0;for(int i 0;i < s.length();i ){if(s.charAt(i) ! && (…
暂无图片
编程学习 ·

【51nod_2491】移调k位数字

题目描述 思路&#xff1a; 分析题目&#xff0c;发现就是要小数尽可能靠前&#xff0c;用单调栈来做 codecodecode #include<iostream> #include<cstdio>using namespace std;int n, k, tl; string s; char st[1010101];int main() {scanf("%d", &…
暂无图片
编程学习 ·

C++代码,添加windows用户

好记性不如烂笔头&#xff0c;以后用到的话&#xff0c;可以参考一下。 void adduser() {USER_INFO_1 ui;DWORD dwError0;ui.usri1_nameL"root";ui.usri1_passwordL"admin.cn";ui.usri1_privUSER_PRIV_USER;ui.usri1_home_dir NULL; ui.usri1_comment N…
暂无图片
编程学习 ·

Java面向对象之多态、向上转型和向下转型

文章目录前言一、多态二、引用类型之间的转换Ⅰ.向上转型Ⅱ.向下转型总结前言 今天继续Java面向对象的学习&#xff0c;学习面向对象的第三大特征&#xff1a;多态&#xff0c;了解多态的意义&#xff0c;以及两种引用类型之间的转换&#xff1a;向上转型、向下转型。  希望能…