C#接口实现自定义的 Token 鉴权过滤器,用于保护 Web API 接口不被未授权用户访问
lucky.帅 2024-06-10 15:03:03 阅读 82
一、创建一个BaseApiController类,并继承ApiController
public class BaseApiController : ApiController { /// <summary> /// 构造函数赋值 /// </summary> public BaseApiController() { TokenValue = HttpContext.Current.Session[LoginID] ?? ""; HttpContext.Current.Request.Headers.Add("TokenValue", TokenValue.ToString()); } /// <summary> /// 数据库上下文 /// </summary> //public WYDBContext db = WYDBContextFactory.GetDbContext(); /// <summary> /// token值 登录后赋值请求api的时候添加到header中 /// </summary> public static object TokenValue { get; set; } = ""; /// <summary> /// 登录者账号 /// </summary> public static string LoginID { get; set; } = ""; }
二、在web API 自带的App_Start文件夹下创建一个TokenCheckFilter类
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.Http;using System.Net.Http;using System.Text;using System.Web.Helpers;using System.Web.Http.Controllers;using System.Web.Security;using System.Net;namespace WebApplication1.App_Start{ public class TokenCheckFilter : AuthorizeAttribute { /// <summary> /// 重写基类的验证方式,加入自定义的Ticket验证 /// </summary> /// <param name="actionContext"></param> public override void OnAuthorization(HttpActionContext actionContext) { //var content = actionContext.Request.Properties["MS_HttpContext"] as HttpContextBase; //获取token(请求头里面的值) var token = HttpContext.Current.Request.Headers["TokenValue"] ?? ""; //是否为空 if (!string.IsNullOrEmpty(token.ToString())) { //解密用户ticket,并校验用户名密码是否匹配 if (ValidateTicket(token.ToString())) base.IsAuthorized(actionContext); else HandleUnauthorizedRequest(actionContext); } //如果取不到身份验证信息,并且不允许匿名访问,则返回未验证403 else { var attributes = actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().OfType<AllowAnonymousAttribute>(); bool isAnonymous = attributes.Any(a => a is AllowAnonymousAttribute); if (isAnonymous) base.OnAuthorization(actionContext); else HandleUnauthorizedRequest(actionContext); } } //校验用户名密码(对Session匹配,或数据库数据匹配) private bool ValidateTicket(string encryptToken) { try { //解密Ticket var strTicket = FormsAuthentication.Decrypt(encryptToken).UserData; //从Ticket里面获取用户名和密码 var index = strTicket.IndexOf("&"); string userName = strTicket.Substring(0, index); string password = strTicket.Substring(index + 1); //取得session,不通过说明用户退出,或者session已经过期 var token = HttpContext.Current.Session[userName]; if (token == null) return false; //对比session中的令牌 if (token.ToString() == encryptToken) return true; return false; } catch { return false; } } /// <summary> /// 重写HandleUnauthorizedRequest /// </summary> /// <param name="filterContext"></param> protected override void HandleUnauthorizedRequest(HttpActionContext filterContext) { base.HandleUnauthorizedRequest(filterContext); 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"); } }}
三、使用Token鉴权过滤器 例:
[HttpPost][Route("api/Test/Login")]public object Login([FromBody]JObject jobject){ string name = jobject["name"].ToString(); string password = jobject["password"].ToString(); if (name == "" || name != "admin") { return Json( new { ret = -1, success = false ,msg = "密码错误!"}); } FormsAuthenticationTicket token = new FormsAuthenticationTicket(0, name, DateTime.Now, DateTime.Now.AddHours(12), true, $"{name}&{password}", FormsAuthentication.FormsCookiePath); //返回登录结果、用户信息、用户验证票据信息 var _token = FormsAuthentication.Encrypt(token); //将身份信息保存在session中,验证当前请求是否是有效请求 LoginID = name; TokenValue = _token; HttpContext.Current.Session[LoginID] = _token; //HttpContext.Current.Session. return Json(new { ret = 1, success = true , data = _token });//给前端token并保存在session中}[HttpGet][Route("api/Test/LoginTest")][TokenCheckFilter]public object Test(){ return Json(new { ret = 1, success = true, data = "", msg = "登录成功!" });}
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。