1.10 操作业务

1.10.1【必须】部署CSRF防御机制

CSRF是指跨站请求伪造(Cross-site request forgery),是web常见的攻击之一。对于可重放的敏感操作请求,需部署CSRF防御机制。可参考以下两种常见的CSRF防御方式

  • 设置CSRF Token

    服务端给合法的客户颁发CSRF Token,客户端在发送请求时携带该token供服务端校验,服务端拒绝token验证不通过的请求。以此来防止第三方构造合法的恶意操作链接。Token的作用域可以是Request级或者Session级。下面以Session级CSRF Token进行示例

    1. 登录成功后颁发Token,并同时存储在服务端Session中

      1. String uuidToken = UUID.randomUUID().toString();
      2. map.put("token", uuidToken);
      3. request.getSession().setAttribute("token",uuidToken );
      4. return map;
    2. 创建Filter

      1. public class CsrfFilter implements Filter {
      2. ...
      3. HttpSession session = req.getSession();
      4. Object token = session.getAttribute("token");
      5. String requestToken = req.getParameter("token");
      6. if(StringUtils.isBlank(requestToken) || !requestToken.equals(token)){
      7. AjaxResponseWriter.write(req, resp, ServiceStatusEnum.ILLEGAL_TOKEN, "非法的token");
      8. return;
      9. }
      10. ...

    ​ CSRF Token应具备随机性,保证其不可预测和枚举。另外由于浏览器会自动对表单所访问的域名添加相应的cookie信息,所以CSRF Token不应该通过Cookie传输。

  • 校验Referer头

    通过检查HTTP请求的Referer字段是否属于本站域名,非本站域名的请求进行拒绝。

    这种校验方式需要注意两点:

    1. 要需要处理Referer为空的情况,当Referer为空则拒绝请求
    2. 注意避免例如qq.com.evil.com 部分匹配的情况。
1.10.2【必须】权限校验

对于非公共操作,应当校验当前访问账号进行操作权限(常见于CMS)和数据权限校验。

  1. 验证当前用户的登录态
  2. 从可信结构中获取经过校验的当前请求账号的身份信息(如:session)。禁止从用户请求参数或Cookie中获取外部传入不可信用户身份直接进行查询。
  3. 校验当前用户是否具备该操作权限
  4. 校验当前用户是否具备所操作数据的权限。避免越权。
1.10.3【建议】加锁操作

对于有次数限制的操作,比如抽奖。如果操作的过程中资源访问未正确加锁。在高并发的情况下可能造成条件竞争,导致实际操作成功次数多于用户实际操作资格次数。此类操作应加锁处理。