using System; using System.Linq; using System.Net; using System.Net.Http; using System.Reflection; using System.Security.Claims; using System.Threading; using System.Threading.Tasks; using System.Web.Http; using System.Web.Http.Controllers; using System.Web.Http.Filters; using WebAPI.Models; using WebAPI.Utility; public class JwtAuthorizeAttribute : AuthorizationFilterAttribute { private json objjson = new json(); private SQLHelper.ClsCN oCN = new SQLHelper.ClsCN(); private Pub_Class.ClsXt_SystemParameter oSystemParameter = new Pub_Class.ClsXt_SystemParameter(); private string campanyName = ""; public JwtAuthorizeAttribute() { if (oSystemParameter.ShowBill(ref DBUtility.ClsPub.sErrInfo)) { campanyName = oSystemParameter.omodel.WMS_CampanyName; } } // 同步鉴权 public override void OnAuthorization(HttpActionContext actionContext) { try { // 检查匿名访问(认证) if (IsAnonymousAllowed(actionContext)) return; // 获取Token var token = GetTokenFromHeader(actionContext); if (string.IsNullOrEmpty(token)) { HandleUnauthorized(actionContext); return; } // 验证Token // 可以增加更细粒度的控制,添加 根据组织ID 判断(问题: 公司名不能使用中文,可能需要添加英文字段) var principal = JWTHelper.ValidateToken(token); if (principal == null) { HandleUnauthorized(actionContext); return; } // 设置用户 actionContext.RequestContext.Principal = principal; // 验证是否拥有访问模块的权限 // 有两种判断方式 一种是通过角色去判断,一种是通过用户去判断 目前暂时不做区分,后续可增加系统参数来进行区分 // 安全控制器描标签 var controllerAttr = actionContext.ControllerContext?.ControllerDescriptor?.GetCustomAttributes().FirstOrDefault(); // 安全获取Action标签 var actionAttr = actionContext.ActionDescriptor?.GetCustomAttributes().FirstOrDefault(); string PermissionStr = string.Empty; // 判断控制器级别上是否启用了鉴权标签 if(controllerAttr != null && !string.IsNullOrWhiteSpace(controllerAttr?.HModName)) { PermissionStr += controllerAttr.HModName; // 查看是否需要更细粒度的控制 if(actionAttr != null && !string.IsNullOrWhiteSpace(actionAttr?.Operate)) { // 该动作对应的模块名和控制器名是否不一致 if (string.IsNullOrWhiteSpace(actionAttr.HModName)) { PermissionStr = actionAttr.HModName + actionAttr.Operate; } else { PermissionStr += actionAttr.Operate; } } if(!string.IsNullOrWhiteSpace(PermissionStr)) { if (!DBUtility.ClsPub.Security_Log(PermissionStr, 1, false, JWTHelper.getUserName(token))) { HandleForbidden(actionContext); return; } } }else if (actionAttr != null && !string.IsNullOrWhiteSpace(actionAttr?.HModName) && !string.IsNullOrWhiteSpace(actionAttr?.Operate)) { // 单独在动作上启用鉴权功能 PermissionStr = actionAttr.HModName + actionAttr.Operate; if (!string.IsNullOrWhiteSpace(PermissionStr)) { if (!DBUtility.ClsPub.Security_Log(PermissionStr, 1, false, JWTHelper.getUserName(token))) { HandleForbidden(actionContext); return; } } } } catch (Exception e) { HandleError(actionContext, e.Message); } } // 异步鉴权 public override Task OnAuthorizationAsync(HttpActionContext actionContext, CancellationToken cancellationToken) { OnAuthorization(actionContext); return Task.FromResult(0); } // 是否允许匿名访问(控制器级别和动作级别都可用) private bool IsAnonymousAllowed(HttpActionContext context) { return context.ActionDescriptor.GetCustomAttributes().Count > 0 || context.ControllerContext.ControllerDescriptor.GetCustomAttributes().Count > 0; } // 从Header提取Token private string GetTokenFromHeader(HttpActionContext context) { var authHeader = context.Request.Headers.Authorization; if (authHeader != null && authHeader.Scheme.Equals("Bearer", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(authHeader.Parameter)) { return authHeader.Parameter; } return null; } // 401 未授权 private void HandleUnauthorized(HttpActionContext context) { var response = new HttpResponseMessage(HttpStatusCode.Unauthorized); objjson.code = "0"; objjson.count = 0; objjson.Message = "未授权,请登录后重试"; response.Content = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(objjson), System.Text.Encoding.UTF8, "application/json"); context.Response = response; } // 403 无权限 private void HandleForbidden(HttpActionContext context) { var response = new HttpResponseMessage(HttpStatusCode.Forbidden); objjson.code = "0"; objjson.count = 0; objjson.Message = "您没有该模块权限,请与管理员联系!"; response.Content = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(objjson), System.Text.Encoding.UTF8, "application/json"); context.Response = response; } private void HandleError(HttpActionContext context, string ErrorInfo) { var response = new HttpResponseMessage(HttpStatusCode.InternalServerError); objjson.code = "0"; objjson.count = 0; objjson.Message = "服务器异常: " + ErrorInfo; response.Content = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(objjson), System.Text.Encoding.UTF8, "application/json"); context.Response = response; } }