SpringBoot傳統(tǒng)WEB應(yīng)用開(kāi)啟CSRF的流程
CSRF 是什么?
CSRF(Cross-Site Request Forgery,跨站請(qǐng)求偽造) 是一種常見(jiàn)的Web安全漏洞。攻擊者利用受害者已經(jīng)登錄的合法會(huì)話,誘使受害者執(zhí)行非本意的操作。
簡(jiǎn)單比喻:
想象你在咖啡店會(huì)員卡里有錢,你每次消費(fèi)只需要說(shuō)“用會(huì)員卡支付”。攻擊者偽裝成服務(wù)員,在你面前說(shuō)“用會(huì)員卡轉(zhuǎn)賬100元到XXX賬戶”。因?yàn)槟阋呀?jīng)在咖啡店的系統(tǒng)中“登錄”了(身份已認(rèn)證),系統(tǒng)就會(huì)執(zhí)行這個(gè)操作。
CSRF攻擊原理:
攻擊流程:
- 用戶登錄:用戶登錄正常的網(wǎng)站A(如銀行網(wǎng)站),獲得登錄憑證(Cookie/Session)
- 用戶訪問(wèn)惡意網(wǎng)站:用戶在同一個(gè)瀏覽器中訪問(wèn)了攻擊者的網(wǎng)站B
- 惡意請(qǐng)求:網(wǎng)站B通過(guò)隱藏表單、圖片src、AJAX等方式,向網(wǎng)站A發(fā)送請(qǐng)求
- 自動(dòng)攜帶憑證:瀏覽器會(huì)自動(dòng)攜帶網(wǎng)站A的Cookie
- 網(wǎng)站A執(zhí)行請(qǐng)求:網(wǎng)站A看到合法Cookie,誤以為是用戶的自愿操作
攻擊示例:
<!-- 惡意網(wǎng)站上的代碼 --> <img src="https://your-bank.com/transfer?to=hacker&amount=10000" width="0" height="0" /> <!-- 或隱藏表單 --> <form action="https://your-bank.com/change-email" method="POST"> <input type="hidden" name="email" value="hacker@evil.com"> </form> <script>document.forms[0].submit();</script>
為什么有時(shí)要禁用CSRF保護(hù)?
適用禁用場(chǎng)景:
純API服務(wù)(無(wú)瀏覽器交互)
# 移動(dòng)App通過(guò)API訪問(wèn)后端 # 使用Token認(rèn)證(JWT/OAuth),而不是Session Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
僅提供非狀態(tài)改變的操作
GET /api/users # 只讀操作,通常不需要CSRF POST /api/transfer # 寫操作,需要CSRF
微服務(wù)內(nèi)部通信
# 服務(wù)間調(diào)用使用服務(wù)憑證,而不是用戶會(huì)話 service-to-service: true
某些特殊框架/場(chǎng)景
// GraphQL通常使用token而不是session // 或某些實(shí)時(shí)通信應(yīng)用
具體框架中的禁用示例:
Spring Security:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable() // 禁用CSRF
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic(); // 使用HTTP Basic認(rèn)證
}
}Django:
# settings.py
CSRF_COOKIE_SECURE = False # 禁用CSRF
# 或針對(duì)特定視圖
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def api_view(request):
passCSRF保護(hù)機(jī)制對(duì)比:
| 保護(hù)機(jī)制 | 工作原理 | 適用場(chǎng)景 |
|---|---|---|
| CSRF Token | 服務(wù)器生成Token,表單/請(qǐng)求必須攜帶 | 傳統(tǒng)Web應(yīng)用 |
| SameSite Cookie | Cookie僅在同站請(qǐng)求中發(fā)送 | 現(xiàn)代瀏覽器支持 |
| 雙重Cookie驗(yàn)證 | 客戶端讀取Cookie并附加到請(qǐng)求 | 兼容性較好 |
| Referer檢查 | 檢查請(qǐng)求來(lái)源 | 簡(jiǎn)單但不可靠 |
| 無(wú)(禁用) | 不驗(yàn)證 | 純API、內(nèi)部服務(wù) |
何時(shí)應(yīng)該啟用/禁用CSRF?
應(yīng)該啟用CSRF的場(chǎng)景:
- ? 傳統(tǒng)的基于Session的Web應(yīng)用
- ? 用戶通過(guò)瀏覽器訪問(wèn)的表單提交
- ? 需要用戶交互的操作(轉(zhuǎn)賬、修改數(shù)據(jù))
- ? 使用Cookie/Session進(jìn)行身份認(rèn)證
可以禁用CSRF的場(chǎng)景:
- ? 純REST API,使用JWT/OAuth Token認(rèn)證
- ? 僅限移動(dòng)App訪問(wèn)的后端服務(wù)
- ? 微服務(wù)間的內(nèi)部通信
- ? 只讀的公共API
- ? 使用其他認(rèn)證方式(API Key、HMAC簽名)
禁用CSRF后的替代安全方案:
# 替代方案示例: 1. JWT Token認(rèn)證: 每次請(qǐng)求攜帶: Authorization: Bearer <token> 2. API Key + Secret: 請(qǐng)求簽名: X-Signature: sha256(api_secret + request_data) 3. OAuth 2.0: 使用Access Token進(jìn)行授權(quán) 4. CORS限制: Access-Control-Allow-Origin: https://trusted-domain.com 5. Rate Limiting: 限制請(qǐng)求頻率防止濫用
最佳實(shí)踐建議:
// 在Spring中,可以針對(duì)不同端點(diǎn)配置不同的CSRF策略
public class SecurityConfig {
protected void configure(HttpSecurity http) {
http
// 對(duì)Web頁(yè)面啟用CSRF
.csrf(csrf -> csrf
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler())
)
.requireCsrfProtectionMatcher(
new RequestMatcher() {
public boolean matches(HttpServletRequest request) {
// 僅對(duì)特定路徑啟用CSRF
return request.getRequestURI().startsWith("/web/");
}
})
.and()
// API端點(diǎn)使用無(wú)狀態(tài)認(rèn)證
.authorizeRequests()
.antMatchers("/api/**").authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS); // API無(wú)狀態(tài)
}
}驗(yàn)證 CSRF 是否生效
- 檢查 Cookie:登錄后查看瀏覽器是否有
XSRF-TOKENCookie - 測(cè)試請(qǐng)求:
- 直接發(fā)送 POST 請(qǐng)求應(yīng)該被拒絕(403 錯(cuò)誤)
- 攜帶正確的 CSRF Token 的請(qǐng)求應(yīng)該成功
- 檢查響應(yīng)頭:某些配置下,響應(yīng)頭會(huì)包含 CSRF Token
# 使用 curl 測(cè)試
# 1. 先獲取 CSRF Token(從登錄后的 Cookie 或響應(yīng)頭)
# 2. 發(fā)送帶 CSRF Token 的請(qǐng)求
curl -X POST http://localhost:8080/api/test \
-H "Content-Type: application/json" \
-H "X-XSRF-TOKEN: YOUR_CSRF_TOKEN" \
-H "Cookie: XSRF-TOKEN=YOUR_CSRF_TOKEN" \
-d '{"data": "test"}'總結(jié):
禁用CSRF的前提條件:
- 應(yīng)用不使用Cookie/Session進(jìn)行身份認(rèn)證
- 請(qǐng)求來(lái)源可控(如僅限移動(dòng)App、內(nèi)部服務(wù))
- 已實(shí)施同等或更強(qiáng)的安全措施替代
- 確認(rèn)攻擊面不會(huì)因此擴(kuò)大
黃金法則:
如果用戶通過(guò)瀏覽器訪問(wèn)你的網(wǎng)站,并且網(wǎng)站使用了Cookie/Session,那么永遠(yuǎn)不要禁用CSRF保護(hù)。只有在完全理解風(fēng)險(xiǎn)并有替代方案時(shí),才考慮為API服務(wù)禁用CSRF。
到此這篇關(guān)于springboot~傳統(tǒng)WEB應(yīng)用開(kāi)啟CSRF的文章就介紹到這了,更多相關(guān)java多線程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
淺談mybatisPlus的Ipage分頁(yè)和map參數(shù)的問(wèn)題
這篇文章主要介紹了mybatisPlus的Ipage分頁(yè)和map參數(shù)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
springboot 如何配置多個(gè)jndi數(shù)據(jù)源
這篇文章主要介紹了springboot 如何配置多個(gè)jndi數(shù)據(jù)源的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07
淺談java反射和自定義注解的綜合應(yīng)用實(shí)例
本篇文章主要介紹了java反射和自定義注解的綜合應(yīng)用,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09
mybatisPlus實(shí)現(xiàn)邏輯刪除,自動(dòng)生成創(chuàng)建時(shí)間和更新時(shí)間方式
MyBatisPlus框架中,通過(guò)@TableField(fill=FieldFill.INSERT)和@TableField(fill=FieldFill.UPDATE)注解可以實(shí)現(xiàn)在插入和更新時(shí)自動(dòng)填充字段,比如創(chuàng)建時(shí)間和更新時(shí)間,使用@TableLogic注解標(biāo)識(shí)邏輯刪除字段2024-09-09
IntelliJ IDEA Java項(xiàng)目手動(dòng)添加依賴 jar 包的方法(圖解)
這篇文章主要介紹了IntelliJ IDEA Java項(xiàng)目手動(dòng)添加依賴 jar 包,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04

