我们的项目从.net framework 转到 net core webapi,不想改太多代码,特别是身份认证,之前是直接在 QueryString 中传输 token 来认证,各个 action 上有个自定义的 CheckLogin 标签,要改成的 JWT 认证体系,工作量巨大,于是想到利用过滤器来实现自定义的身份认证过程。

先建一个空的 Attribute,不用任何功能,有这个 Attribute 的 Action 表示都需要认证

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class LoginCheckAttribute : Attribute
{
}

然后建一个 IActionFilter

public class AuthFilter : IActionFilter
{
    private const string UnauthorizedMessage = "授权失效或过期,请重新登录。";

    public void OnActionExecuting(ActionExecutingContext context)
    {
        var controllerInfo = context.ActionDescriptor as ControllerActionDescriptor;
        var needcheck = controllerInfo?.EndpointMetadata.Any(_ => _.GetType() == typeof(LoginCheckAttribute)) ?? false;
        if (needcheck)
        {
            var token = context.HttpContext.Request.Query["token"].ToString();

            ApiResult<object>? result = null;
            if (string.IsNullOrEmpty(token))
            {
                result = new() { Code = 888, Message = UnauthorizedMessage };
            }
            else
            {
                var uinfo = Factory.SessionAccess.GetUserByToken(token);//根据token得到用户信息
                if (uinfo == null)
                {
                    result = new() { Code = 888, Message = UnauthorizedMessage };
                }
                else
                {
                    if (uinfo.State != (int)AdminState.enable)
                    {
                        result = new() { Code = 888, Message = "账号无法使用" };
                    }
                    else
                        context.HttpContext.Items["user"] = uinfo;//用户信息存在会话中,供业务逻辑中调用
                }
            }

            if(result != null)
            {
                context.Result = new UnauthorizedObjectResult(result);
            }
        }
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
    }
}

然后在 program.cs 中加入过滤器:

builder.Services.AddControllers().AddMvcOptions(options => options.Filters.Insert(0, new AuthFilter()));

业务逻辑中需要用到用户信息的地方这样获取:

    public UserDetails? UserInfo
    {
        get
        {
            if (MyHttpContext.Current == null) return null;
            if(MyHttpContext.Current.Items.TryGetValue("user", out var value))
            {
                return value as UserDetails;
            }
            return null;
        }
    }

标签: none

添加新评论