上篇博客,当没有权限的用户访问一些资源时,返回的是403错误,403对于用户来说是一个莫名其妙的数字,我们当然要处理成友好的提示。
关于错误处理,翻看了一下Nancy的源码,是这样处理的,见下面地址:
https://github.com/NancyFx/Nancy/blob/master/src/Nancy/ErrorHandling/DefaultStatusCodeHandler.cs
其实Nancy是允许我们采用相同的办法处理,现在把DefaultStatusCodeHandler.cs的源码复制下来,改成我们自己的CustomStatusCode.cs如下,关于详细说明,参考Nancy源码DefaultStatusCodeHandler.cs。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
using
Nancy;
using
Nancy.ErrorHandling;
using
Nancy.ViewEngines;
using
System.Collections.Generic;
using
System.IO;
using
System.Linq;
using
System.Text;
using
Nancy.Responses.Negotiation;
using
Nancy.Extensions;
using
Nancy.IO;
namespace
NancySelfHostWeb
{
public
class
CustomStatusCode: IStatusCodeHandler
{
private
const
string
DisableErrorTracesTrueMessage =
"Error details are currently disabled. Please set <code>StaticConfiguration.DisableErrorTraces = false;</code> to enable."
;
private
readonly
IDictionary<HttpStatusCode,
string
> errorMessages;
private
readonly
IDictionary<HttpStatusCode,
string
> errorPages;
private
readonly
IResponseNegotiator responseNegotiator;
private
readonly
HttpStatusCode[] supportedStatusCodes = { HttpStatusCode.Forbidden, HttpStatusCode.NotFound};
public
CustomStatusCode(IResponseNegotiator responseNegotiator)
{
this
.errorMessages =
new
Dictionary<HttpStatusCode,
string
>
{
{ HttpStatusCode.Forbidden,
"查看是否有授权!"
},
{ HttpStatusCode.NotFound,
"找不到你要的资源!"
}
};
this
.errorPages =
new
Dictionary<HttpStatusCode,
string
>
{
{ HttpStatusCode.Forbidden, LoadResource(
"NancySelfHostWeb.403.html"
) },
{ HttpStatusCode.NotFound, LoadResource(
"NancySelfHostWeb.404.html"
) }
};
this
.responseNegotiator = responseNegotiator;
}
public
bool
HandlesStatusCode(HttpStatusCode statusCode, NancyContext context)
{
return
this
.supportedStatusCodes.Any(s => s == statusCode);
}
public
void
Handle(HttpStatusCode statusCode, NancyContext context)
{
if
(context.Response !=
null
&& context.Response.Contents !=
null
&& !ReferenceEquals(context.Response.Contents, Response.NoBody))
{
return
;
}
if
(!
this
.errorMessages.ContainsKey(statusCode) || !
this
.errorPages.ContainsKey(statusCode))
{
return
;
}
Response existingResponse =
null
;
if
(context.Response !=
null
)
{
existingResponse = context.Response;
}
context.NegotiationContext =
new
NegotiationContext();
var
result =
new
DefaultStatusCodeHandlerResult(statusCode,
this
.errorMessages[statusCode], StaticConfiguration.DisableErrorTraces ? DisableErrorTracesTrueMessage : context.GetExceptionDetails());
try
{
context.Response =
this
.responseNegotiator.NegotiateResponse(result, context);
context.Response.StatusCode = statusCode;
if
(existingResponse !=
null
)
{
context.Response.ReasonPhrase = existingResponse.ReasonPhrase;
}
return
;
}
catch
(ViewNotFoundException)
{
}
this
.ModifyResponse(statusCode, context, result);
}
private
void
ModifyResponse(HttpStatusCode statusCode, NancyContext context, DefaultStatusCodeHandlerResult result)
{
if
(context.Response ==
null
)
{
context.Response =
new
Response { StatusCode = statusCode };
}
var
contents =
this
.errorPages[statusCode];
if
(!
string
.IsNullOrEmpty(contents))
{
contents = contents.Replace(
"[DETAILS]"
, result.Details);
}
context.Response.ContentType =
"text/html"
;
context.Response.Contents = s =>
{
using
(
var
writer =
new
StreamWriter(
new
UnclosableStreamWrapper(s), Encoding.UTF8))
{
writer.Write(contents);
}
};
}
private
static
string
LoadResource(
string
filename)
{
// 获取当前资源文件
var
resourceStream =
typeof
(CustomStatusCode).Assembly.GetManifestResourceStream(
string
.Format(
"{0}"
, filename));
if
(resourceStream ==
null
)
{
return
string
.Empty;
}
using
(
var
reader =
new
StreamReader(resourceStream))
{
return
reader.ReadToEnd();
}
}
internal
class
DefaultStatusCodeHandlerResult
{
public
DefaultStatusCodeHandlerResult(HttpStatusCode statusCode,
string
message,
string
details)
{
this
.StatusCode = statusCode;
this
.Message = message;
this
.Details = details;
}
public
HttpStatusCode StatusCode {
get
;
private
set
; }
public
string
Message {
get
;
private
set
; }
public
string
Details {
get
;
private
set
; }
}
}
}
|
这样还可以把Nancy内置的500,404错误改成我们自定义的显示。
有时觉得这样太麻烦,可以自大在Module中去判断登录用户是否具有角色,代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
using
Nancy;
using
Nancy.Security;
using
System.Linq;
namespace
TestSelfHostWeb.Modules
{
public
class
IndexModule : NancyModule
{
public
IndexModule()
{
//开启全局验证
this
.RequiresAuthentication();
Get[
"/"
] = parameters =>
{
//开启角色验证,只有该角色可以访问本路由
//this.RequiresClaims("admin");
//自己判断登录角色具有权限
if
(!
this
.Context.CurrentUser.Claims.Contains(
"admin"
))
{
return
View[
"error"
];
//定义一个错误页面error.cshtml即可
}
return
View[
"index"
];
};
}
}
}
|
附件:http://down.51cto.com/data/2367711
本文转自桂素伟51CTO博客,原文链接: http://blog.51cto.com/axzxs/1774297,如需转载请自行联系原作者