XSS和CSRF解决方案

  1. XSS/CSRF
    1. XSS
    2. CSRF攻击(钓鱼网站)
    3. 相关工具类

XSS/CSRF

XSS 和 CSRF 攻击详解 - 掘金 (juejin.cn)

针对以上两种攻击设计解决方案如下

XSS

XSS攻击主要利用的是JavaScript获取浏览器信息,只要token值无法被JavaScript获取即可。

设置HttpOnlyCookie

//  设置Cookie值的方法
public static void setHttpOnlyCookieValue(HttpServletResponse response, String cookieName, String cookieValue){

    Cookie cookie = new Cookie(cookieName, cookieValue);
    cookie.setMaxAge(maxAge); // Cookie的存活时间(自定义)
    cookie.setPath("/"); // 默认路径
    cookie.setHttpOnly(true);
    response.addCookie(cookie);
}

CSRF攻击(钓鱼网站)

主要利用了浏览器携带的cookie,虽然无法直接获取cookie内部隐私信息,但可以利用cookie伪造请求。

解决方案

设置Cookie的SameSite属性

Strict

这意味浏览器仅对同一站点的请求发送 cookie,即请求来自设置 cookie 的站点。如果请求来自不同的域名或协议(即使是相同域名),则携带有 SameSite=Strict 属性的 cookie 不会被发送。

Lax

这意味着 cookie 不会在跨站请求中被发送,如:加载图像或框架(frame)的请求。但 cookie 在用户从外部站点导航到源站时,cookie 也会被发送(例如,访问一个链接)。这是 SameSite 属性未被设置时的默认行为。

None

这意味着浏览器在跨站和同站请求中均会发送 cookie。在设置这一属性值时,必须同时设置 Secure 属性,就像这样:SameSite=None; Secure

//设置Cookie值的方法 提供sameSite策略
public static void setHttpOnlyCookieValue(HttpServletResponse response, String cookieName, String cookieValue,String sameSite){
    ResponseCookie cookie = ResponseCookie.from(cookieName, cookieValue).sameSite(sameSite)
            .httpOnly(true)
            .maxAge(maxAge)
            .path("/")
            .build();
    response.setHeader(HttpHeaders.SET_COOKIE,cookie.toString());
}

设置csrfToken

解析请求头中的csrfToken和session中的是否相同

//csrf-token
String csrf = (String)request.getSession().getAttribute(Constant.CSRF_TOKEN);
String headerCsrf = request.getHeader(Constant.CSRF_TOKEN);
if (csrf == null || headerCsrf == null || !csrf.equals(headerCsrf)){
    //csrfToken不匹配,拒绝服务
    return;
}

前端请求头设置csrfToken

// http request拦截器 添加一个请求拦截器
axios.interceptors.request.use(function (config) {
    
    let token = sessionStorage.getItem(CSRF_TOKEN)
    if (token != null) {
        //将token放到请求头发送给服务器
        config.headers.csrf = token;
        return config;
    }
    return config;
}, function (error) {
    // Do something with request error
    return Promise.reject(error);
});

相关工具类

package pers.os467.management.utils;

import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseCookie;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

/**
 *根据cookie的key来找到某一个具体的cookie,因为api中我们只能获取所有cookie
 * 获取单个cookie的话只能通过标识去过滤,这样就很麻烦,所以我们可以封装一个工具类
 * 来提高开发速率
 * by os467
 */
public class CookieUtils {

    private static final Integer maxAge = 60 * 60 * 24;

    //构造方法私有化
    private CookieUtils(){

    }

    /**
     * 根据key来获取cookie
     * @return
     */
    public static Cookie findCookie(Cookie[] cookies,String cookieName){

        if (cookies == null || cookies.length == 0 || cookieName == null){
            return null;
        }

        //遍历cookie数组
        for (Cookie cookie : cookies) {
            if (cookie.getName().equals(cookieName)){
                return cookie;
            }
        }
        return null;

    }

    //	设置Cookie值的方法
    public static void setHttpCookieValue(HttpServletResponse response, String cookieName, String cookieValue){

        Cookie cookie = new Cookie(cookieName, cookieValue);
        cookie.setMaxAge(maxAge); // Cookie的存活时间(自定义)
        cookie.setPath("/"); // 默认路径
        response.addCookie(cookie);
    }

    public static void setHttpCookieValue(HttpServletResponse response, String cookieName, String cookieValue,Integer maxAge){

        Cookie cookie = new Cookie(cookieName, cookieValue);
        cookie.setMaxAge(maxAge); // Cookie的存活时间(自定义)
        cookie.setPath("/"); // 默认路径
        response.setHeader("set-cookie","SameSite=strict");
        response.addCookie(cookie);
    }

    //	设置Cookie值的方法
    public static void setHttpOnlyCookieValue(HttpServletResponse response, String cookieName, String cookieValue){

        Cookie cookie = new Cookie(cookieName, cookieValue);
        cookie.setMaxAge(maxAge); // Cookie的存活时间(自定义)
        cookie.setPath("/"); // 默认路径
        cookie.setHttpOnly(true);
        response.addCookie(cookie);
    }


    //设置Cookie值的方法 提供sameSite策略
    public static void setHttpOnlyCookieValue(HttpServletResponse response, String cookieName, String cookieValue,String sameSite){
        ResponseCookie cookie = ResponseCookie.from(cookieName, cookieValue).sameSite(sameSite)
                .httpOnly(true)
                .maxAge(maxAge)
                .path("/")
                .build();
        response.setHeader(HttpHeaders.SET_COOKIE,cookie.toString());
    }



    public static void deleteCookie(HttpServletResponse response, String cookieName) {
        try {
            String deleteValue = URLEncoder.encode("", "utf-8");
            CookieUtils.setHttpCookieValue(response,cookieName,deleteValue,0);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
}

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以邮件至 1300452403@qq.com

文章标题:XSS和CSRF解决方案

字数:944

本文作者:Os467

发布时间:2023-12-26, 17:48:10

最后更新:2023-12-26, 17:49:03

原始链接:https://os467.github.io/2023/12/26/xss%E6%94%BB%E5%87%BB%E5%92%8Ccsrf%E6%94%BB%E5%87%BB%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

×

喜欢就点赞,疼爱就打赏