时间:2025-12-31 11:22
人气:
作者:admin
CSRF(Cross-Site Request Forgery,跨站请求伪造) 是一种常见的Web安全漏洞。攻击者利用受害者已经登录的合法会话,诱使受害者执行非本意的操作。
想象你在咖啡店会员卡里有钱,你每次消费只需要说“用会员卡支付”。攻击者伪装成服务员,在你面前说“用会员卡转账100元到XXX账户”。因为你已经在咖啡店的系统中“登录”了(身份已认证),系统就会执行这个操作。
<!-- 恶意网站上的代码 -->
<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>
纯API服务(无浏览器交互)
# 移动App通过API访问后端
# 使用Token认证(JWT/OAuth),而不是Session
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
仅提供非状态改变的操作
GET /api/users # 只读操作,通常不需要CSRF
POST /api/transfer # 写操作,需要CSRF
微服务内部通信
# 服务间调用使用服务凭证,而不是用户会话
service-to-service: true
某些特殊框架/场景
// GraphQL通常使用token而不是session
// 或某些实时通信应用
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认证
}
}
Django:
# settings.py
CSRF_COOKIE_SECURE = False # 禁用CSRF
# 或针对特定视图
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def api_view(request):
pass
| 保护机制 | 工作原理 | 适用场景 |
|---|---|---|
| CSRF Token | 服务器生成Token,表单/请求必须携带 | 传统Web应用 |
| SameSite Cookie | Cookie仅在同站请求中发送 | 现代浏览器支持 |
| 双重Cookie验证 | 客户端读取Cookie并附加到请求 | 兼容性较好 |
| Referer检查 | 检查请求来源 | 简单但不可靠 |
| 无(禁用) | 不验证 | 纯API、内部服务 |
# 替代方案示例:
1. JWT Token认证:
每次请求携带: Authorization: Bearer <token>
2. API Key + Secret:
请求签名: X-Signature: sha256(api_secret + request_data)
3. OAuth 2.0:
使用Access Token进行授权
4. CORS限制:
Access-Control-Allow-Origin: https://trusted-domain.com
5. Rate Limiting:
限制请求频率防止滥用
// 在Spring中,可以针对不同端点配置不同的CSRF策略
public class SecurityConfig {
protected void configure(HttpSecurity http) {
http
// 对Web页面启用CSRF
.csrf(csrf -> csrf
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler())
)
.requireCsrfProtectionMatcher(
new RequestMatcher() {
public boolean matches(HttpServletRequest request) {
// 仅对特定路径启用CSRF
return request.getRequestURI().startsWith("/web/");
}
})
.and()
// API端点使用无状态认证
.authorizeRequests()
.antMatchers("/api/**").authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS); // API无状态
}
}
XSRF-TOKEN Cookie# 使用 curl 测试
# 1. 先获取 CSRF Token(从登录后的 Cookie 或响应头)
# 2. 发送带 CSRF Token 的请求
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"}'
禁用CSRF的前提条件:
黄金法则:
如果用户通过浏览器访问你的网站,并且网站使用了Cookie/Session,那么永远不要禁用CSRF保护。只有在完全理解风险并有替代方案时,才考虑为API服务禁用CSRF。
作者:仓储大叔,张占岭,
荣誉:微软MVP
QQ:853066980
支付宝扫一扫,为大叔打赏!
下一篇:剑指offer-58、对称二叉树
【从0到1构建一个ClaudeAgent】协作-Agent团队