CSRF(Cross Site Request Forgery, 跨站域请求伪造)是一种网络的攻击方式,它在 2007 年曾被列为互联网 20 大安全隐患之一,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用也就是人们所知道的钓鱼网站。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,并且攻击方式几乎相左。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。
防御CSRF手段
解决方案:使用图形验证码 防止机器模拟接口请求攻击,在调用核心业务接口时,比如支付、下单、等接口,最好使用手机短信验证验证或是人脸识别,防止其他用户使用Token伪造请求。
下面来引申其它的一些知识 - - -> 使用Token机制,防止页面重复提交。
基于Token方式防止API接口幂等
需求:
业务要求
:页面的数据只能被点击提交一次发生原因
:由于重复点击或者网络重发,或者 nginx 重发等情况会导致数据被重复提交解决办法:
集群环境
:采用 token 加 redis(redis 单线程的,处理需要排队)单 JVM 环境
:采用 token 加 redis 或 token 加 jvm 内存处理流程:
- 数据提交前要向服务的申请 token,token 放到 redis 或 jvm 内存,token 有效时间 提交后后台校验 token,同时删除 token,生成新的 token 返回。
- token 特点:要申请,一次有效性,可以限流
客户端每次在调用接口的时候,需要在请求头中,传递令牌参数,每次令牌只能用一次。
一旦使用之后,就会被删除,这样可以有效防止重复提交。
步骤:
- 生成令牌接口
- 接口中获取令牌验证
生成令牌接口:
public class TokenUtils { private static Map<String, Object> tokenMap = new ConcurrentHashMap<String, Object>(); // 获取token public static synchronized String getToken() { // 1.生成令牌 String token = "token-" + System.currentTimeMillis(); // 2.存入tokenMap tokenMap.put(token, token); return token; } // 验证token,并且删除对应的token public static Boolean exisToken(String token) { // 1.从集合中获取token Object result = tokenMap.get(token); if (result == null) { return false; } // 2.删除对应的token tokenMap.remove(token); return true; } }
接口中获取令牌验证:
@RestController public class OrderController { @Autowired private OrderMapper orderMapper; // 获取Token @RequestMapping("/getToken") public String getToken() { return TokenUtils.getToken(); } // 验证Token @RequestMapping(value = "/addOrder", produces = "application/json; charset=utf-8") public String addOrder(@RequestBody OrderEntity orderEntity, HttpServletRequest request) { String token = request.getHeader("token"); if (StringUtils.isEmpty(token)) { return "参数错误!"; } if (!TokenUtils.exisToken(token)) { return "请勿重复提交!"; } int result = orderMapper.addOrder(orderEntity); return result > 0 ? "添加成功" : "添加失败" + ""; } }
总结