我正在使用基于声明的OAuth-JWT承载令牌安全性,并使用ClaimsPrincipalPermission属性装饰我的web api操作方法,如下所示:
[ClaimsPrincipalPermission(SecurityAction.Demand, Operation = "Admin", Resource = "DeleteUser")]
[HttpPost]
public IHttpActionResult Delete(string id)
{
//code for getting user details based on id rcvd.
...
...
return Ok("Dropped user:" + userName);
}
这很有效。问题是我在没有所需权限的情况下访问此Web api方法的所有用户都会收到安全性异常。这是一个非常丑陋的字符串,如下面的那个
{
"message": "An error has occurred.",
"exceptionMessage": "ID4266: Request for ClaimsPrincipalPermission failed for: Action: 'System.Collections.ObjectModel.Collection`1[System.Security.Claims.Claim]', Resource: 'System.Collections.ObjectModel.Collection`1[System.Security.Claims.Claim]'.",
"exceptionType": "System.Security.SecurityException",
"stackTrace": " at System.IdentityModel.Services.ClaimsPrincipalPermission.Demand()\r\n at System.Security.PermissionSet.DemandNonCAS()\r\n at TheService.Controllers.SampleController.Drop(String id) in d:\\Entire\\path\\to\\source\\code\\here\\SampleController.cs:line 37\r\n at lambda_method(Closure , Object , Object[] )\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"
}
我希望将其格式化得更好,我只会发送错误消息,其中包含自定义错误字符串和数字,如下所示:
{
"message": "not enough privileges.",
"err_type": "Security Issue",
"err_code": "Some custom error code here"
}
有关如何完成此操作的任何提示?
答案 0 :(得分:0)
public class GlobalSecurityExceptionFilter : ExceptionFilterAttribute
{ public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
var exceptionType = actionExecutedContext.Exception.GetType();
if (exceptionType == typeof (SecurityException))
{
actionExecutedContext.Response = ActionExecutedContext.Request.CreateErrorResponse(HttpStatusCode.Forbidden,JsonConvert.SerializeObject(new { message = "not enough privileges.", err_type="Security Issue", err_code = "Some custom error code here"}));
}
base.OnException(actionExecutedContext);
}
}
然后在webapi.config中:
public static void Register(HttpConfiguration config)
{
config.Filters.Add(new GlobalSecurityExceptionFilter());
您可能还想从ClaimsPrincipalPermission中提取一些属性:
var claimsPermissionAttrType = typeof (ClaimsPrincipalPermissionAttribute);
var stackTrace = new StackTrace(e);
for (int i=0; i<stackTrace.FrameCount; i++)
{
var attribute = stackTrace.GetFrame(i).GetMethod().GetCustomAttributes(claimsPermissionAttrType, false).FirstOrDefault();
if (attribute == null) continue;
var attr = (ClaimsPrincipalPermissionAttribute) attribute;
return new SecurityException(string.Format("Security check failed. Principal = {3}, Action = {0}, Operation={1}, Resource={2}\n",
attr.Action, attr.Operation, attr.Resource, ClaimsPrincipal.Current.Identity.Name), e);
}
不诚实,不要提及this