C#接口实现自定义的 Token 鉴权过滤器,用于保护 Web API 接口不被未授权用户访问

发布时间:2024年01月04日

一、创建一个TokenHolder类,定义一个Token属性

public class TokenHolder
    {
        public static string Token { get; set; }
    }

二、在web API 自带的App_Start文件夹下创建一个TokenCheckFilter类

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Web;
using System.Web.Helpers;
using System.Web.Http;
using System.Web.Http.Controllers;

namespace WebApplication1.App_Start
{
    //继承 AuthorizeAttribute 类,创建一个名为 TokenCheckFilter 的特性类
    public class TokenCheckFilter : AuthorizeAttribute
    {
        //重写 OnAuthorization 方法,实现自定义授权逻辑
        public override void OnAuthorization(HttpActionContext actionContext)
        {
            //从请求头中获取 TokenValue 参数值
            var token = HttpContext.Current.Request.Headers["TokenValue"] ?? "";
            //如果 Token 值不为空,则校验 Token 是否有效
            if (!string.IsNullOrEmpty(token.ToString()))
            {
                if (ValidateTicket(token.ToString()))
                {
                    base.IsAuthorized(actionContext);//如果 Token 有效,则允许访问 API 接口
                }
                else
                {
                    HandleUnauthorizedRequest(actionContext);//如果 Token 无效,则返回 403 状态码,并提示错误信息
                }
            }
            else
            { 
                //如果 Token 值为空,则判断当前 API 接口是否允许匿名访问
                var attributes = actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().OfType<AllowAnonymousAttribute>();
                bool isAnonymous = attributes.Any(a => a is AllowAnonymousAttribute);
                if (isAnonymous) base.OnAuthorization(actionContext);
                //如果接口不允许匿名访问,则返回 403 状态码,并提示错误信息
                else HandleUnauthorizedRequest(actionContext);
            }
        }
        //校验 Token 是否有效的方法
        private bool ValidateTicket(string encryptToken)
        {
            try
            {
                if (encryptToken == TokenHolder.Token)//从 TokenHolder 类中获取保存的 Token 值,进行比较
                {
                    return true;//如果 Token 有效,则返回 true
                }
                else
                {
                    return false;//如果 Token 无效,则返回 false
                }
            }
            catch (Exception)
            {
                return false;//如果 Token异常,也返回 false
            }
        }
        //重写 HandleUnauthorizedRequest 方法,实现自定义错误返回信息
        protected override void HandleUnauthorizedRequest(HttpActionContext filterContext)
        {
            base.HandleUnauthorizedRequest(filterContext);//调用父类的 HandleUnauthorizedRequest 方法

            var response = filterContext.Response = filterContext.Response ?? new HttpResponseMessage();
            //状态码401改为其他状态码来避免被重定向。最合理的是改为403,表示服务器拒绝。
            response.StatusCode = HttpStatusCode.Forbidden;
            var content = new
            {
                success = false,
                ret = -2,
                errs = "服务端拒绝访问:你没有权限?,或者掉线了?"
            };
            response.Content = new StringContent(Json.Encode(content), Encoding.UTF8, "application/json");//返回 JSON 格式的错误信息
        }
        private int GetUserId()
        {
            var username = HttpContext.Current.User.Identity.Name;//从 HttpContext 中获取当前登录用户的用户名
            var userid = GetUser(username)?.id;//从 HttpContext 中获取当前登录用户的id
            return userid ?? 0;
        }
        //查询数据库中用户的id和用户名
        private User GetUser(string username)
        {
            DataSet dataSet = package.sqllog("select * from user where username='" + username + "'");
            DataRow row = dataSet.Tables[0].Rows[0];
            User user = new User()
            {
                id = Convert.ToInt32(row["id"].ToString()),
                username = row["username"].ToString()
            };
            return user;
        }
        public class User
        {
            public int id { get; set; }
            public string username { get; set; }
        }
    }
}

三、使用Token鉴权过滤器 例:

        [HttpGet]
        [System.Web.Http.Route("api/index/shili")]
        [TokenCheckFilter]
        public object get(int x) {
            int y = 200;
            int S = x + y;
            return Json(new { ret = 200, success = true, data = S });
        }

四、使用接口时需要在请求头里加入你自定义的Token,然后进行接口访问

文章来源:https://blog.csdn.net/qq_64948696/article/details/135336792
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。