安全
源码及系列文章目录
Git 源码 :https://github.com/tangsong1995/TS.Microservices
CSDN 资源 :https://download.csdn.net/download/qq_33649351/34675095
系列文章目录 :https://blog.csdn.net/qq_33649351/article/details/120998558
防跨站请求伪造
攻击过程
要素:
- 用户已登录“GoodSite”
- “GoodSite”通过 Cookie 存储和传递身份信息
- 用户访问了“BadSite”
防御
- 不使用 Cookie 来存储和传输身份信息,使用 JWT 或其他方式进行身份认证
- 若使用了 Cookie ,使用 AntiforgeryToken 来防御
- 避免使用 GET 作为业务操作的请求方法
AntiforgeryToken
Startup 中配置:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddAntiforgery(options =>
{
options.HeaderName = "X-CSRF-TOKEN";
});
//开启全局AntiforgeryToken验证
services.AddMvc(options => options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()));
...
}
客户端需要在请求头加上 X-CSRF-TOKEN 传入 Cookie 的值,服务器会验证 header 的值与 Cookie 的值是否一致,如果不一致,会认为是非法请求。
若不想使用过滤器开启全局 AntiforgeryToken 验证,可以使用 [ValidateAntiForgeryToken] 和 [AutoValidateAntiforgeryToken] 标签对对接口开启 AntiforgeryToken 验证, [AutoValidateAntiforgeryToken] 对 get 请求不生效。
防开放重定向攻击
攻击过程
要素:
- “好站点”的重定向未验证目标 URL
- 用户访问了“坏站点”
防御
- 使用 LocalRedirect 来处理重定向
- 验证重定向的目标域名是否合法
[HttpPost]
public async Task<IActionResult> Login(string returnUrl)
{
// TODO : Login
if (string.IsNullOrEmpty(returnUrl))
{
return Content("登录成功");
}
try
{
var uri = new Uri(returnUrl);
//TODO : 验证 uri 是否有效
return Redirect(returnUrl);
}
catch
{
return Redirect("/");
}
}
防跨站脚本
攻击过程
防御
- 对用户提交内容进行验证,拒绝恶意脚本
- 对用户提交的内容进行编码 UrlEncoder、JavaScriptEncoder、UrlEncoder
- 慎用 HtmlString 和 HtmlHelper.Raw
- 身份信息 Cookie 设置为 HttpOnly
- 避免使用 Path 传递带有不受信的字符,使用 Query 进行传递
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
options.LoginPath = "/home/login";
//options.Cookie.HttpOnly = true; //默认true
});
...
}
跨域请求
CORS
- CORS 是浏览器允许跨域发起请求“君子协定”
- 它是浏览器行为协议
- 它并不会让服务器拒绝其它途径发起的 HTTP 请求
- 开启时需要考虑是否存在被恶意网站攻击的情形
CORS 请求头
- Origin 请求源
- Access-Control-Request-Method 期望请求发起的请求方法
- Access-Control-Request-Headers 期望请求发起的请求头
CORS 响应头
- Access-Control-Allow-Origin 是否允许跨域
- Access-Control-Allow-Credentials 是否允许携带身份认证信息
- Access-Control-Expose-Headers 是否允许脚本访问响应头
- Access-Control-Max-Age 有效时间
- Access-Control-Allow-Methods 允许的请求方法
- Access-Control-Allow-Headers 允许的请求头
默认支持的 Expose Headers
- Cache-Control
- Content-Language
- Content-Type
- Expires
- Last-Modified
- Pragma
CORS 过程
启用 CORS
配置 CORS:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddCors(options =>
{
options.AddPolicy("api", builder =>
{
builder.WithOrigins("https://localhost:5001").AllowAnyHeader().AllowCredentials().WithExposedHeaders("abc");
builder.SetIsOriginAllowed(orgin => true).AllowCredentials().AllowAnyHeader();
});
});
...
}
以上代码的意义为:
- WithOrigins允许跨域的源是 “https://localhost:5001” ,
- AllowAnyHeader 允许携带Header
- AllowCredentials 允许携带身份认证信息
- WithExposedHeaders 允许访问的响应头
- SetIsOriginAllowed 批量设置
启用 CORS:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseCors();
...
}
在 api 上使用 [EnableCors(“api”)] 标签允许 CORS 。