Csrf攻击的解决思路

1.什么是Csrf攻击

关于什么是csrf攻击,这里不多赘述,可以参考下面的文章,写的不错。
浅谈CSRF攻击方式,今天这里主要记录如何防御csrf攻击。

2.防御csrf攻击

这里csrf攻击的防御采用以下方案:在用户发送请求之前,先通过ajax请求访问后台,生成一个随机数作为一个token,并将这个token保存在session,同时返回到前台页面,然后前台页面将这个token放在请求中,发送到后台,被过滤器拦截,判断请求中带的token和session中的token进行匹配,如果一致,则转发请求到真正的controller中处理。下面给出代码,因为这是自己这两天和朋友闲着做的一个项目,准备先写后台接口,还没有前台代码,所以这里只给出后台代码。

生成token的方法

/**
 * 工具类
 * @author HXY
 */
public class Utils {

    /**
     * 生成固定长度的token:包含大小写字母和数字
     * @param length 需要的token的长度
     * @return
     */
    public static String createToken(int length) {

        //token
        StringBuffer token = new StringBuffer();
        SecureRandom random = new SecureRandom();

        for (int i = 0; i < length; i++) {
            int num = random.nextInt(3);
            switch (num) {
                case 0:
                    //生成0-9之间的数字
                    token.append((int)random.nextFloat() * 9);
                    break;
                case 1:
                    //生成A-Z之间的字符
                    token.append((char) (65 + (int) (random.nextFloat() * 26)));
                    break;
                case 2:
                    //生成a-z之间的字符
                    token.append((char) (97 + (int) (random.nextFloat() * 26)));
                    break;
                default:
                    break;

            }
        }
        return token.toString();
    }
}

CsrfController ,所有请求在到达后台前,先访问这个controller,获取token,并且将token绑定在请求中,然后发送到后台。这里省去了前台代码。

/**
 * CsrfController 生成token,存储在session中并返回到前台
 * @author HXY
 * @version 1.0
 */
@RestController
public class CsrfController {

    private final static Logger logger = LoggerFactory.getLogger(CsrfController.class);

    /**
     * 在服务端保存token,并将生成的token返回到前台
     * @param request
     * @return 生成的token
     */
    @GetMapping("/honeybee/csrf")
    @ResponseBody
    public HoneyResult createToken(HttpServletRequest request) {
        logger.info("begin create csrfToken...");
        String token = Utils.createToken(128);
        //保存在session中
        request.getSession().setAttribute("token",token);
        logger.info("end create csrfToken...");
        //作为json格式返回到页面
        return new HoneyResult(token);

    }
}

过滤器,拦截所有请求,验证token。

/**
 * 防止csrf攻击的过滤器
 * @author HXY
 */
@WebFilter(urlPatterns = "/*", filterName = "csrfFilter")
public class CsrfFilter extends OncePerRequestFilter {

    private final static String REQUEST_METHOD_POST = "POST";
    private final static String REQUEST_METHOD_GET = "GET";
    private final static Logger logger = LoggerFactory.getLogger(CsrfFilter.class);

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        logger.info("Begin csrf...");

        //服务器端存储的token
        String token_server = (String) request.getSession().getAttribute("token");
        //客户端请求的token
        String token_client = (String) request.getAttribute("token");

        //如果是post请求,则做csrf校验
        if (REQUEST_METHOD_POST.equals(request.getMethod())) {
            if (null != token_client && null != token_server && token_client.equals(token_server)) {
                filterChain.doFilter(request, response);
            }
            logger.info("Csrf parameter is invalid...");
        }else if (REQUEST_METHOD_GET.equals(request.getMethod())){
            filterChain.doFilter(request,response);
        }

        logger.info("End Csrf...");
    }
}

代码是可以运行的。还没有页面,没有测试能不能有效防御csrf攻击。后续会进行严格测试,并进行补充。

代码地址:https://github.com/HXY-0227/honeybee

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

半__夏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值