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