diff options
author | 杨宇千 <crupest@outlook.com> | 2019-08-19 22:52:01 +0800 |
---|---|---|
committer | 杨宇千 <crupest@outlook.com> | 2019-08-19 22:52:01 +0800 |
commit | 577d282f8e8f44f1a48b9dbf7dd90e8ef50c7a53 (patch) | |
tree | 5725e61da570be86173472d68bd6df521e593b65 /Timeline | |
parent | 134173eda92de04961dc69757b257c1c547d88a4 (diff) | |
download | timeline-577d282f8e8f44f1a48b9dbf7dd90e8ef50c7a53.tar.gz timeline-577d282f8e8f44f1a48b9dbf7dd90e8ef50c7a53.tar.bz2 timeline-577d282f8e8f44f1a48b9dbf7dd90e8ef50c7a53.zip |
Add check for content in avatar put.
Diffstat (limited to 'Timeline')
-rw-r--r-- | Timeline/Controllers/UserAvatarController.cs | 26 | ||||
-rw-r--r-- | Timeline/Filters/ContentHeaderAttributes.cs | 48 | ||||
-rw-r--r-- | Timeline/Models/Http/Common.cs | 19 |
3 files changed, 89 insertions, 4 deletions
diff --git a/Timeline/Controllers/UserAvatarController.cs b/Timeline/Controllers/UserAvatarController.cs index 89d2650c..ffadcb86 100644 --- a/Timeline/Controllers/UserAvatarController.cs +++ b/Timeline/Controllers/UserAvatarController.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.Logging; using System;
using System.Threading.Tasks;
using Timeline.Authenticate;
+using Timeline.Filters;
using Timeline.Models.Http;
using Timeline.Services;
@@ -22,6 +23,9 @@ namespace Timeline.Controllers public const int Put_BadFormat_CantDecode = -2011;
public const int Put_BadFormat_UnmatchedFormat = -2012;
public const int Put_BadFormat_BadSize = -2013;
+ public const int Put_Content_TooBig = -2021;
+ public const int Put_Content_UnmatchedLength_Less = -2022;
+ public const int Put_Content_UnmatchedLength_Bigger = -2023;
public const int Delete_UserNotExist = -3001;
public const int Delete_Forbid = -3002;
@@ -55,7 +59,7 @@ namespace Timeline.Controllers [HttpGet("users/{username}/avatar")]
[Authorize]
- public async Task<IActionResult> Get(string username)
+ public async Task<IActionResult> Get([FromRoute] string username)
{
const string IfModifiedSinceHeaderKey = "If-Modified-Since";
try
@@ -83,9 +87,15 @@ namespace Timeline.Controllers [HttpPut("users/{username}/avatar")]
[Authorize]
+ [RequireContentType, RequireContentLength]
[Consumes("image/png", "image/jpeg", "image/gif", "image/webp")]
public async Task<IActionResult> Put(string username)
{
+ var contentLength = Request.ContentLength.Value;
+ if (contentLength > 1000 * 1000 * 10)
+ return BadRequest(new CommonResponse(ErrorCodes.Put_Content_TooBig,
+ "Content can't be bigger than 10MB."));
+
if (!User.IsAdmin() && User.Identity.Name != username)
{
_logger.LogInformation($"Attempt to put a avatar of other user as a non-admin failed. Operator Username: {User.Identity.Name} ; Username To Put Avatar: {username} .");
@@ -95,8 +105,16 @@ namespace Timeline.Controllers try
{
- var data = new byte[Convert.ToInt32(Request.ContentLength)];
- await Request.Body.ReadAsync(data, 0, data.Length);
+ var data = new byte[contentLength];
+ var bytesRead = await Request.Body.ReadAsync(data);
+
+ if (bytesRead != contentLength)
+ return BadRequest(new CommonResponse(ErrorCodes.Put_Content_UnmatchedLength_Less,
+ $"Content length in header is {contentLength} but actual length is {bytesRead}."));
+
+ if (Request.Body.ReadByte() != -1)
+ return BadRequest(new CommonResponse(ErrorCodes.Put_Content_UnmatchedLength_Bigger,
+ $"Content length in header is {contentLength} but actual length is bigger than that."));
await _service.SetAvatar(username, new Avatar
{
@@ -121,7 +139,7 @@ namespace Timeline.Controllers [HttpDelete("users/{username}/avatar")]
[Authorize]
- public async Task<IActionResult> Delete(string username)
+ public async Task<IActionResult> Delete([FromRoute] string username)
{
if (!User.IsAdmin() && User.Identity.Name != username)
{
diff --git a/Timeline/Filters/ContentHeaderAttributes.cs b/Timeline/Filters/ContentHeaderAttributes.cs new file mode 100644 index 00000000..14685a01 --- /dev/null +++ b/Timeline/Filters/ContentHeaderAttributes.cs @@ -0,0 +1,48 @@ +using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Timeline.Models.Http;
+
+namespace Timeline.Filters
+{
+ public class RequireContentTypeAttribute : ActionFilterAttribute
+ {
+ public override void OnActionExecuting(ActionExecutingContext context)
+ {
+ if (context.HttpContext.Request.ContentType == null)
+ {
+ context.Result = new BadRequestObjectResult(CommonResponse.MissingContentType());
+ }
+ }
+ }
+
+ public class RequireContentLengthAttribute : ActionFilterAttribute
+ {
+ public RequireContentLengthAttribute()
+ : this(true)
+ {
+
+ }
+
+ public RequireContentLengthAttribute(bool requireNonZero)
+ {
+ RequireNonZero = requireNonZero;
+ }
+
+ public bool RequireNonZero { get; set; }
+
+ public override void OnActionExecuting(ActionExecutingContext context)
+ {
+ if (context.HttpContext.Request.ContentLength == null)
+ {
+ context.Result = new BadRequestObjectResult(CommonResponse.MissingContentLength());
+ return;
+ }
+
+ if (RequireNonZero && context.HttpContext.Request.ContentLength.Value == 0)
+ {
+ context.Result = new BadRequestObjectResult(CommonResponse.ZeroContentLength());
+ return;
+ }
+ }
+ }
+}
diff --git a/Timeline/Models/Http/Common.cs b/Timeline/Models/Http/Common.cs index b4932754..50f6836e 100644 --- a/Timeline/Models/Http/Common.cs +++ b/Timeline/Models/Http/Common.cs @@ -9,6 +9,10 @@ namespace Timeline.Models.Http /// For example a required field is null.
/// </summary>
public const int InvalidModel = -100;
+
+ public const int Header_Missing_ContentType = -111;
+ public const int Header_Missing_ContentLength = -112;
+ public const int Header_Zero_ContentLength = -113;
}
public static CommonResponse InvalidModel(string message)
@@ -16,6 +20,21 @@ namespace Timeline.Models.Http return new CommonResponse(ErrorCodes.InvalidModel, message);
}
+ public static CommonResponse MissingContentType()
+ {
+ return new CommonResponse(ErrorCodes.Header_Missing_ContentType, "Header Content-Type is required.");
+ }
+
+ public static CommonResponse MissingContentLength()
+ {
+ return new CommonResponse(ErrorCodes.Header_Missing_ContentLength, "Header Content-Length is missing or of bad format.");
+ }
+
+ public static CommonResponse ZeroContentLength()
+ {
+ return new CommonResponse(ErrorCodes.Header_Zero_ContentLength, "Header Content-Length must not be 0.");
+ }
+
public CommonResponse()
{
|