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 ? "添加成功" : "添加失败" + "";
}
}
总结