亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

spring security中的csrf防御原理(跨域請(qǐng)求偽造)

 更新時(shí)間:2019年12月11日 10:31:51   作者:yaoh371  
這篇文章主要介紹了spring security中的csrf防御機(jī)制原理解析(跨域請(qǐng)求偽造),本文通過(guò)實(shí)例代碼詳解的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

什么是csrf?

csrf又稱跨域請(qǐng)求偽造,攻擊方通過(guò)偽造用戶請(qǐng)求訪問(wèn)受信任站點(diǎn)。CSRF這種攻擊方式在2000年已經(jīng)被國(guó)外的安全人員提出,但在國(guó)內(nèi),直到06年才開(kāi)始被關(guān)注,08年,國(guó)內(nèi)外的多個(gè)大型社區(qū)和交互網(wǎng)站分別爆出CSRF漏洞,如:NYTimes.com(紐約時(shí)報(bào))、Metafilter(一個(gè)大型的BLOG網(wǎng)站),YouTube和百度HI......而現(xiàn)在,互聯(lián)網(wǎng)上的許多站點(diǎn)仍對(duì)此毫無(wú)防備,以至于安全業(yè)界稱CSRF為“沉睡的巨人”。

舉個(gè)例子,用戶通過(guò)表單發(fā)送請(qǐng)求到銀行網(wǎng)站,銀行網(wǎng)站獲取請(qǐng)求參數(shù)后對(duì)用戶賬戶做出更改。在用戶沒(méi)有退出銀行網(wǎng)站情況下,訪問(wèn)了攻擊網(wǎng)站,攻擊網(wǎng)站中有一段跨域訪問(wèn)的代碼,可能自動(dòng)觸發(fā)也可能點(diǎn)擊提交按鈕,訪問(wèn)的url正是銀行網(wǎng)站接受表單的url。因?yàn)槎紒?lái)自于用戶的瀏覽器端,銀行將請(qǐng)求看作是用戶發(fā)起的,所以對(duì)請(qǐng)求進(jìn)行了處理,造成的結(jié)果就是用戶的銀行賬戶被攻擊網(wǎng)站修改。

解決方法基本上都是增加攻擊網(wǎng)站無(wú)法獲取到的一些表單信息,比如增加圖片驗(yàn)證碼,可以杜絕csrf攻擊,但是除了登陸注冊(cè)之外,其他的地方都不適合放驗(yàn)證碼,因?yàn)榻档土司W(wǎng)站易用性

相關(guān)介紹:

http://baike.baidu.com/view/1609487.htm?fr=aladdin

spring-servlet中配置csrf

 <!-- Spring csrf 攔截器 -->
 <mvc:interceptors>
  <mvc:interceptor>
   <mvc:mapping path="/login" />
   <bean class="com.wangzhixuan.commons.csrf.CsrfInterceptor" />
  </mvc:interceptor>
 </mvc:interceptors>

在類(lèi)中聲明Csrf攔截器,用來(lái)生成或去除CsrfToken

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.wangzhixuan.commons.scan.ExceptionResolver;
import com.wangzhixuan.commons.utils.WebUtils;

/**
 * Csrf攔截器,用來(lái)生成或去除CsrfToken
 * 
 * @author L.cm
 */
public class CsrfInterceptor extends HandlerInterceptorAdapter {
 private static final Logger logger = LogManager.getLogger(ExceptionResolver.class);
 
 @Autowired 
 private CsrfTokenRepository csrfTokenRepository;
 
 @Override
 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  HandlerMethod handlerMethod = (HandlerMethod) handler;
  // 非控制器請(qǐng)求直接跳出
  if (!(handler instanceof HandlerMethod)) {
   return true;
  }
  CsrfToken csrfToken = handlerMethod.getMethodAnnotation(CsrfToken.class);
  // 判斷是否含有@CsrfToken注解
  if (null == csrfToken) {
   return true;
  }
  // create、remove同時(shí)為true時(shí)異常
  if (csrfToken.create() && csrfToken.remove()) {
   logger.error("CsrfToken attr create and remove can Not at the same time to true!");
   return renderError(request, response, Boolean.FALSE, "CsrfToken attr create and remove can Not at the same time to true!");
  }
  // 創(chuàng)建
  if (csrfToken.create()) {
   CsrfTokenBean token = csrfTokenRepository.generateToken(request);
   csrfTokenRepository.saveToken(token, request, response);
   // 緩存一個(gè)表單頁(yè)面地址的url
   csrfTokenRepository.cacheUrl(request, response);
   request.setAttribute(token.getParameterName(), token);
   return true;
  }
  // 判斷是否ajax請(qǐng)求
  boolean isAjax = WebUtils.isAjax(handlerMethod);
  // 校驗(yàn),并且清除
  CsrfTokenBean tokenBean = csrfTokenRepository.loadToken(request);
  if (tokenBean == null) {
   return renderError(request, response, isAjax, "CsrfToken is null!");
  }
  String actualToken = request.getHeader(tokenBean.getHeaderName());
  if (actualToken == null) {
   actualToken = request.getParameter(tokenBean.getParameterName());
  }
  if (!tokenBean.getToken().equals(actualToken)) {
   return renderError(request, response, isAjax, "CsrfToken not eq!");
  }
  return true;
 }
 
 private boolean renderError(HttpServletRequest request, HttpServletResponse response, 
   boolean isAjax, String message) throws IOException {
  // 獲取緩存的cacheUrl
  String cachedUrl = csrfTokenRepository.getRemoveCacheUrl(request, response);
  // ajax請(qǐng)求直接拋出異常,因?yàn)閧@link ExceptionResolver}會(huì)去處理
  if (isAjax) {
   throw new RuntimeException(message);
  }
  // 非ajax CsrfToken校驗(yàn)異常,先清理token
  csrfTokenRepository.saveToken(null, request, response);
  logger.info("Csrf[redirectUrl]:\t" + cachedUrl);
  response.sendRedirect(cachedUrl);
  return false;
 }

 /**
  * 用于清理@CsrfToken保證只能請(qǐng)求成功一次
  */
 @Override
 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
   ModelAndView modelAndView) throws Exception {
  HandlerMethod handlerMethod = (HandlerMethod) handler;
  // 非控制器請(qǐng)求直接跳出
  if (!(handler instanceof HandlerMethod)) {
   return;
  }
  CsrfToken csrfToken = handlerMethod.getMethodAnnotation(CsrfToken.class);
  if (csrfToken == null || !csrfToken.remove()) {
   return;
  }
  csrfTokenRepository.getRemoveCacheUrl(request, response);
  csrfTokenRepository.saveToken(null, request, response);
 }

}

聲明Csrf過(guò)濾注解,通過(guò)標(biāo)注來(lái)過(guò)濾對(duì)應(yīng)的請(qǐng)求

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Csrf過(guò)濾注解
 * @author L.cm
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CsrfToken {
 boolean create() default false;
 boolean remove() default false;
}

建立實(shí)例對(duì)象(操作對(duì)象)

import java.io.Serializable;
import org.springframework.util.Assert;
public class CsrfTokenBean implements Serializable {
 private static final long serialVersionUID = -6865031901744243607L;
 private final String token;
 private final String parameterName;
 private final String headerName;
 /**
  * Creates a new instance
  * @param headerName the HTTP header name to use
  * @param parameterName the HTTP parameter name to use
  * @param token the value of the token (i.e. expected value of the HTTP parameter of
  * parametername).
  */
 public CsrfTokenBean(String headerName, String parameterName, String token) {
  Assert.hasLength(headerName, "headerName cannot be null or empty");
  Assert.hasLength(parameterName, "parameterName cannot be null or empty");
  Assert.hasLength(token, "token cannot be null or empty");
  this.headerName = headerName;
  this.parameterName = parameterName;
  this.token = token;
 }
 public String getHeaderName() {
  return this.headerName;
 }
 public String getParameterName() {
  return this.parameterName;
 }
 public String getToken() {
  return this.token;
 }
}

過(guò)濾過(guò)程中需要的倉(cāng)庫(kù)

package com.wangzhixuan.commons.csrf;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface CsrfTokenRepository {
 /**
  * Generates a {@link CsrfTokenBean}
  *
  * @param request the {@link HttpServletRequest} to use
  * @return the {@link CsrfTokenBean} that was generated. Cannot be null.
  */
 CsrfTokenBean generateToken(HttpServletRequest request);
 /**
  * Saves the {@link CsrfTokenBean} using the {@link HttpServletRequest} and
  * {@link HttpServletResponse}. If the {@link CsrfTokenBean} is null, it is the same as
  * deleting it.
  *
  * @param token the {@link CsrfTokenBean} to save or null to delete
  * @param request the {@link HttpServletRequest} to use
  * @param response the {@link HttpServletResponse} to use
  */
 void saveToken(CsrfTokenBean token, HttpServletRequest request,
   HttpServletResponse response);
 /**
  * Loads the expected {@link CsrfTokenBean} from the {@link HttpServletRequest}
  *
  * @param request the {@link HttpServletRequest} to use
  * @return the {@link CsrfTokenBean} or null if none exists
  */
 CsrfTokenBean loadToken(HttpServletRequest request);
 /**
  * 緩存來(lái)源的url
  * @param request request the {@link HttpServletRequest} to use
  * @param response the {@link HttpServletResponse} to use
  */
 void cacheUrl(HttpServletRequest request, HttpServletResponse response);
 /**
  * 獲取并清理來(lái)源的url
  * @param request the {@link HttpServletRequest} to use
  * @param response the {@link HttpServletResponse} to use
  * @return 來(lái)源url
  */
 String getRemoveCacheUrl(HttpServletRequest request, HttpServletResponse response);
}

HttpSessionCsrfTokenRepository

package com.wangzhixuan.commons.csrf;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.wangzhixuan.commons.utils.StringUtils;
public final class HttpSessionCsrfTokenRepository implements CsrfTokenRepository {
 private static final String DEFAULT_CSRF_PARAMETER_NAME = "_csrf";
 private static final String DEFAULT_CSRF_HEADER_NAME = "X-CSRF-TOKEN";
 private static final String DEFAULT_CSRF_TOKEN_ATTR_NAME = HttpSessionCsrfTokenRepository.class
   .getName().concat(".CSRF_TOKEN");
 private static final String DEFAULT_CACHE_URL_ATTR_NAME = HttpSessionCsrfTokenRepository.class
   .getName().concat(".CACHE_URL");
 private String parameterName = DEFAULT_CSRF_PARAMETER_NAME;
 private String headerName = DEFAULT_CSRF_HEADER_NAME;
 private String sessionAttributeName = DEFAULT_CSRF_TOKEN_ATTR_NAME;
 private String cacheUrlAttributeName = DEFAULT_CACHE_URL_ATTR_NAME;
 /*
  * (non-Javadoc)
  *
  * @see org.springframework.security.web.csrf.CsrfTokenRepository#saveToken(org.
  * springframework .security.web.csrf.CsrfToken,
  * javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
  */
 public void saveToken(CsrfTokenBean token, HttpServletRequest request,
   HttpServletResponse response) {
  if (token == null) {
   HttpSession session = request.getSession(false);
   if (session != null) {
    session.removeAttribute(this.sessionAttributeName);
   }
  }
  else {
   HttpSession session = request.getSession();
   session.setAttribute(this.sessionAttributeName, token);
  }
 }
 /*
  * (non-Javadoc)
  *
  * @see
  * org.springframework.security.web.csrf.CsrfTokenRepository#loadToken(javax.servlet
  * .http.HttpServletRequest)
  */
 public CsrfTokenBean loadToken(HttpServletRequest request) {
  HttpSession session = request.getSession(false);
  if (session == null) {
   return null;
  }
  return (CsrfTokenBean) session.getAttribute(this.sessionAttributeName);
 }
 /*
  * (non-Javadoc)
  *
  * @see org.springframework.security.web.csrf.CsrfTokenRepository#generateToken(javax.
  * servlet .http.HttpServletRequest)
  */
 public CsrfTokenBean generateToken(HttpServletRequest request) {
  return new CsrfTokenBean(this.headerName, this.parameterName,
    createNewToken());
 }
 private String createNewToken() {
  return UUID.randomUUID().toString();
 }
 @Override
 public void cacheUrl(HttpServletRequest request, HttpServletResponse response) {
  String queryString = request.getQueryString();
  // 被攔截前的請(qǐng)求URL
  String redirectUrl = request.getRequestURI();
  if (StringUtils.isNotBlank(queryString)) {
   redirectUrl = redirectUrl.concat("?").concat(queryString);
  }
  HttpSession session = request.getSession();
  session.setAttribute(this.cacheUrlAttributeName, redirectUrl);
 }
 @Override
 public String getRemoveCacheUrl(HttpServletRequest request, HttpServletResponse response) {
  HttpSession session = request.getSession(false);
  if (session == null) {
   return null;
  }
  String redirectUrl = (String) session.getAttribute(this.cacheUrlAttributeName);
  if (StringUtils.isBlank(redirectUrl)) {
   return null;
  }
  session.removeAttribute(this.cacheUrlAttributeName);
  return redirectUrl;
 }
}

總結(jié)

以上所述是小編給大家介紹的spring security中的csrf防御原理(跨域請(qǐng)求偽造),希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺(jué)得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!

相關(guān)文章

  • Java中的時(shí)間日期API知識(shí)點(diǎn)總結(jié)

    Java中的時(shí)間日期API知識(shí)點(diǎn)總結(jié)

    本文給大家總結(jié)了Java中的時(shí)間日期API知識(shí)點(diǎn)以及相關(guān)的實(shí)例代碼分享,有興趣的朋友參考學(xué)習(xí)下。
    2018-04-04
  • Java中的zookeeper常用命令詳解

    Java中的zookeeper常用命令詳解

    這篇文章主要介紹了Java中的zookeeper常用命令,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • java代碼執(zhí)行字符串中的邏輯運(yùn)算方法

    java代碼執(zhí)行字符串中的邏輯運(yùn)算方法

    今天小編就為大家分享一篇java代碼執(zhí)行字符串中的邏輯運(yùn)算方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07
  • java 中ArrayList迭代的兩種實(shí)現(xiàn)方法

    java 中ArrayList迭代的兩種實(shí)現(xiàn)方法

    這篇文章主要介紹了java 中ArrayList迭代的兩種實(shí)現(xiàn)方法的相關(guān)資料,Iterator與for語(yǔ)句的結(jié)合,需要的朋友可以參考下
    2017-09-09
  • Spring?Boot?3.x?集成?Feign的詳細(xì)過(guò)程

    Spring?Boot?3.x?集成?Feign的詳細(xì)過(guò)程

    本文闡述了如何在SpringBoot3.x中集成Feign,以實(shí)現(xiàn)微服務(wù)之間的調(diào)用,主要步驟包括:搭建chain-common服務(wù),創(chuàng)建chain-starter/chain-feign-starter服務(wù),集成Feign到chain-system和chain-iot-channel服務(wù),配置Feign,感興趣的朋友一起看看吧
    2024-09-09
  • Java使用easyExcel實(shí)現(xiàn)導(dǎo)入功能

    Java使用easyExcel實(shí)現(xiàn)導(dǎo)入功能

    這篇文章介紹了Java使用easyExcel實(shí)現(xiàn)導(dǎo)入功能的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-10-10
  • Java中枚舉類(lèi)型的一種使用方式

    Java中枚舉類(lèi)型的一種使用方式

    這篇文章主要介紹了Java中枚舉類(lèi)型的一種使用方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • 基于Java代碼實(shí)現(xiàn)游戲服務(wù)器生成全局唯一ID的方法匯總

    基于Java代碼實(shí)現(xiàn)游戲服務(wù)器生成全局唯一ID的方法匯總

    我們?cè)谧龇?wù)器系統(tǒng)開(kāi)發(fā)的時(shí)候,為了適應(yīng)數(shù)據(jù)大并發(fā)的請(qǐng)求,需要插入數(shù)據(jù)庫(kù)之前生成一個(gè)全局的唯一id,糾結(jié)全局唯一id怎么生成呢?下面小編給大家分享Java代碼實(shí)現(xiàn)游戲服務(wù)器生成全局唯一ID的方法匯總,涉及到優(yōu)劣勢(shì)方面的知識(shí)點(diǎn),對(duì)此感興趣的朋友一起看看吧
    2016-10-10
  • springboot配置文件讀取pom文件信息方式

    springboot配置文件讀取pom文件信息方式

    這篇文章主要介紹了springboot配置文件讀取pom文件信息方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Java JSch遠(yuǎn)程執(zhí)行Shell命令的方法

    Java JSch遠(yuǎn)程執(zhí)行Shell命令的方法

    本文主要介紹了Java JSch遠(yuǎn)程執(zhí)行Shell命令,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02

最新評(píng)論