Skip to content

Commit 91feac0

Browse files
committed
custom return format when authorization failure
自定义授权失败返回格式
1 parent e75d015 commit 91feac0

5 files changed

Lines changed: 100 additions & 44 deletions

File tree

Blog.Core/AOP/BlogLogAOP.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using Blog.Core.Hubs;
33
using Blog.Core.Model.Models;
44
using Castle.DynamicProxy;
5+
using Microsoft.AspNetCore.Http;
56
using Microsoft.AspNetCore.SignalR;
67
using Newtonsoft.Json;
78
using StackExchange.Profiling;
@@ -21,10 +22,12 @@ namespace Blog.Core.AOP
2122
public class BlogLogAOP : IInterceptor
2223
{
2324
private readonly IHubContext<ChatHub> _hubContext;
24-
public BlogLogAOP(IHubContext<ChatHub> hubContext)
25+
private readonly IHttpContextAccessor _accessor;
26+
27+
public BlogLogAOP(IHubContext<ChatHub> hubContext,IHttpContextAccessor accessor)
2528
{
2629
_hubContext = hubContext;
27-
30+
_accessor = accessor;
2831
}
2932

3033

@@ -34,8 +37,11 @@ public BlogLogAOP(IHubContext<ChatHub> hubContext)
3437
/// <param name="invocation">包含被拦截方法的信息</param>
3538
public void Intercept(IInvocation invocation)
3639
{
40+
string UserName = _accessor.HttpContext.User.Identity.Name;
41+
3742
//记录被拦截方法信息的日志信息
3843
var dataIntercept = "" +
44+
$"【当前操作用户】:{ UserName} \r\n" +
3945
$"【当前执行方法】:{ invocation.Method.Name} \r\n" +
4046
$"【携带的参数有】: {string.Join(", ", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray())} \r\n";
4147

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Threading.Tasks;
5+
6+
namespace Blog.Core.AuthHelper.Policys
7+
{
8+
public class ApiResponse
9+
{
10+
public int Status { get; set; } = 404;
11+
public object Value { get; set; } = "No Found";
12+
13+
public ApiResponse(StatusCode apiCode)
14+
{
15+
switch (apiCode)
16+
{
17+
case StatusCode.CODE401:
18+
{
19+
Status = 401;
20+
Value = "很抱歉,您无权访问该接口,请确保已经登录!";
21+
}
22+
break;
23+
case StatusCode.CODE403:
24+
{
25+
Status = 403;
26+
Value = "很抱歉,您的访问权限等级不够,联系管理员!";
27+
}
28+
break;
29+
}
30+
}
31+
}
32+
33+
public enum StatusCode
34+
{
35+
CODE401,
36+
CODE403,
37+
CODE404,
38+
CODE500
39+
}
40+
41+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using Blog.Core.AuthHelper.Policys;
2+
using Microsoft.AspNetCore.Authentication;
3+
using Microsoft.AspNetCore.Http;
4+
using Microsoft.Extensions.Logging;
5+
using Microsoft.Extensions.Options;
6+
using Newtonsoft.Json;
7+
using System;
8+
using System.Text.Encodings.Web;
9+
using System.Threading.Tasks;
10+
11+
namespace Blog.Core.AuthHelper
12+
{
13+
public class ApiResponseHandler : AuthenticationHandler<AuthenticationSchemeOptions>
14+
{
15+
public ApiResponseHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
16+
{
17+
}
18+
19+
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
20+
{
21+
throw new NotImplementedException();
22+
}
23+
protected override async Task HandleChallengeAsync(AuthenticationProperties properties)
24+
{
25+
Response.ContentType = "application/json";
26+
Response.StatusCode = StatusCodes.Status401Unauthorized;
27+
await Response.WriteAsync(JsonConvert.SerializeObject(new ApiResponse(StatusCode.CODE401)));
28+
}
29+
30+
protected override async Task HandleForbiddenAsync(AuthenticationProperties properties)
31+
{
32+
Response.ContentType = "application/json";
33+
Response.StatusCode = StatusCodes.Status403Forbidden;
34+
await Response.WriteAsync(JsonConvert.SerializeObject(new ApiResponse(StatusCode.CODE403)));
35+
}
36+
37+
}
38+
}

Blog.Core/AuthHelper/Policys/PermissionHandler.cs

Lines changed: 5 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,12 @@ public PermissionHandler(IAuthenticationSchemeProvider schemes, IRoleModulePermi
4747
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)
4848
{
4949
/*
50-
* .netcore3.0 启用EndpointRouting后,权限filter不再添加到ActionDescriptor ,而将权限直接作为中间件运行,
51-
* 同时所有filter都会添加到endpoint.Metadata。因此,文中的
52-
* context.Resource as Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext不再成立。
53-
*
54-
* 解决方案有两个:
5550
*
5651
* 首先必须在 controller 上进行配置 Authorize ,可以策略授权,也可以角色等基本授权
5752
*
5853
* 1、开启公约, startup 中的全局授权过滤公约:o.Conventions.Insert(0, new GlobalRouteAuthorizeConvention());
5954
*
60-
* 2、不开启公约,使用 IHttpContextAccessor ,也能实现效果,但是不能自定义返回格式,详细看下边配置
55+
* 2、不开启公约,使用 IHttpContextAccessor ,也能实现效果;
6156
*/
6257

6358
// 将最新的角色和接口列表更新
@@ -93,14 +88,7 @@ orderby item.Id
9388
{
9489
if (await handlers.GetHandlerAsync(httpContext, scheme.Name) is IAuthenticationRequestHandler handler && await handler.HandleRequestAsync())
9590
{
96-
//context.Fail();
97-
//return;
98-
99-
//自定义返回数据
100-
var payload = JsonConvert.SerializeObject(new { Code = "401", Message = "很抱歉,您无权访问该接口,请确保已经登录!" });
101-
httpContext.Response.StatusCode = StatusCodes.Status401Unauthorized;
102-
httpContext.Response.ContentType = "application/json";
103-
await httpContext.Response.WriteAsync(payload);
91+
context.Fail();
10492
return;
10593
}
10694
}
@@ -146,17 +134,8 @@ orderby item.Id
146134
//if (currentUserRoles.Count <= 0 || requirement.Permissions.Where(w => currentUserRoles.Contains(w.Role) && w.Url.ToLower() == questUrl).Count() <= 0)
147135
if (currentUserRoles.Count <= 0 || !isMatchRole)
148136
{
149-
// 可以在这里设置跳转页面
150-
//context.Fail();
151-
//return;
152-
153-
var payload = JsonConvert.SerializeObject(new { Code = "403", Message = "很抱歉,您的访问权限等级不够,联系管理员!" });
154-
httpContext.Response.StatusCode = StatusCodes.Status403Forbidden;
155-
httpContext.Response.ContentType = "application/json";
156-
await httpContext.Response.WriteAsync(payload);
137+
context.Fail();
157138
return;
158-
159-
160139
}
161140
}
162141

@@ -167,14 +146,7 @@ orderby item.Id
167146
}
168147
else
169148
{
170-
//context.Fail();
171-
//return;
172-
173-
//自定义返回数据
174-
var payload = JsonConvert.SerializeObject(new { Code = "401", Message = "很抱歉,您无权访问该接口,请确保已经登录!" });
175-
httpContext.Response.StatusCode = StatusCodes.Status401Unauthorized;
176-
httpContext.Response.ContentType = "application/json";
177-
await httpContext.Response.WriteAsync(payload);
149+
context.Fail();
178150
return;
179151
}
180152
return;
@@ -183,14 +155,7 @@ orderby item.Id
183155
//判断没有登录时,是否访问登录的url,并且是Post请求,并且是form表单提交类型,否则为失败
184156
if (!questUrl.Equals(requirement.LoginPath.ToLower(), StringComparison.Ordinal) && (!httpContext.Request.Method.Equals("POST") || !httpContext.Request.HasFormContentType))
185157
{
186-
//context.Fail();
187-
//return;
188-
189-
//自定义返回数据
190-
var payload = JsonConvert.SerializeObject(new { Code = "401", Message = "很抱歉,您无权访问该接口,请确保已经登录!" });
191-
httpContext.Response.StatusCode = StatusCodes.Status401Unauthorized;
192-
httpContext.Response.ContentType = "application/json";
193-
await httpContext.Response.WriteAsync(payload);
158+
context.Fail();
194159
return;
195160
}
196161
}

Blog.Core/Extensions/AuthorizationSetup.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using Blog.Core.Common;
33
using Blog.Core.Common.AppConfig;
44
using Blog.Core.Model.Models;
5+
using Microsoft.AspNetCore.Authentication;
56
using Microsoft.AspNetCore.Authentication.JwtBearer;
67
using Microsoft.AspNetCore.Authorization;
78
using Microsoft.Extensions.DependencyInjection;
@@ -132,7 +133,11 @@ public static void AddAuthorizationSetup(this IServiceCollection services)
132133

133134
//2.1【认证】、core自带官方JWT认证
134135
// 开启Bearer认证
135-
services.AddAuthentication("Bearer")
136+
services.AddAuthentication(o=> {
137+
o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
138+
o.DefaultChallengeScheme = nameof(ApiResponseHandler);
139+
o.DefaultForbidScheme = nameof(ApiResponseHandler);
140+
})
136141
// 添加JwtBearer服务
137142
.AddJwtBearer(o =>
138143
{
@@ -149,7 +154,8 @@ public static void AddAuthorizationSetup(this IServiceCollection services)
149154
return Task.CompletedTask;
150155
}
151156
};
152-
});
157+
})
158+
.AddScheme<AuthenticationSchemeOptions, ApiResponseHandler>(nameof(ApiResponseHandler), o => { });
153159

154160

155161
//2.2【认证】、IdentityServer4 认证 (暂时忽略)

0 commit comments

Comments
 (0)