zoukankan      html  css  js  c++  java
  • Asp.net WebApi的授权安全机制 Basic认证

    1:Home/index.cshtml下面的Html代码

    <div>
            <input  value="1点击先登陆" type="button" id="btnLogin"/><br />
            <input value="2再点击授权后调用接口" type="button" id="btnAuthenrazation" /><br />
     </div>
    

      

      

    2:Home/index 下面的HomeController

    [skipLogAttribute]
    public ActionResult Index()
    {
    return View();
    }

    3: Ajax的模拟代码,先登录,后获取授权,再带上Ticket,后台过滤器校验ok杂可以请求对应的接口

    <script type="text/javascript">
    $(function () {
    var ticket = "";
    $("#btnLogin").click(function () { //---登陆的操作
    $.ajax({
    url: "http://localhost:8899/api/values",
    data: { "uid": "zrf", "pwd": "123" },
    type: "get",
    success: function (res) {
    if (res.result) {
    ticket = res.ticket;
    alert("授权成功"+res.ticket);
    }
    },
    dataType:"json"
    })
    });
    
    //----拿到了Ticket(后台过滤器会判断是否有过授权,以及授权ok才可以调用对应的接口)
    $("#btnAuthenrazation").click(function () {
    $.ajax({
    url: "http://localhost:8899/api/values",
    data: { },
    type: "get",
    beforeSend: function (xhr) {
    xhr.setRequestHeader('Authorization', 'BasicAuth ' + ticket);//--请求其他的接口都需要带上Ticket的
    },
    success: function (res) {
    alert("ok")
    }
    })
    });
    })
    
    //带上Ticket来访问WebApi接口
    $("#btnWithTicket").click(function () {
    $.ajax({
    url: "http://localhost:8899/api/values",
    data: {"id":110},
    type: "get",
    beforeSend: function (xhr) {
    xhr.setRequestHeader('Authorization', 'BasicAuth ' + ticket);//--请求其他的接口都需要带上Ticket的
    },
    success: function (res) {
    if (res.result) {
    alert("调用成功" + res.data);
    }
    }
    })
    })
    

      

      

    4: 创建的一个测试的 WebApiController 如ValuesController:ApiController

    namespace WebApplication1.Controllers
    {
    using System.Web.Security;
    using WebApplication1.Filters;
    public class ValuesController : ApiController
    {
    
    [HttpGet]
    [skipLog]
    public dynamic Login(string uid, string pwd)
    {
    dynamic result = null;
    if ("zrf".Equals(uid) && pwd.Equals("123"))
    {
    FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, "account", DateTime.Now, DateTime.Now.AddSeconds(10), true, $"uid={uid},pwd={pwd}");
    result = new { result = true, ticket = FormsAuthentication.Encrypt(ticket) };
    }
    else {
    result = new { result = false, ticket = ""};
    }
    return result;
    }
    // GET api/<controller>
    [skipLogAttribute]
    public IEnumerable<string> Get()
    {
    return new string[] { "value1", "value2" };
    }
    // GET api/<controller>/5
    [CustomerAuthenrazationFilter]
    public dynamic Get(int id)
    {
    return new { result = true, id = id };
    }
    }
    }
    

     

    5:授权过滤器:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace WebApplication1.Filters
    {
        using System.Net.Http.Headers;
        using System.Web.Http.Controllers;
        using System.Web.Http.Filters;
        using System.Web.Security;
        using System.Web.Http;
        using System.Net;
    
        public class CustomerAuthenrazationFilterAttribute : AuthorizationFilterAttribute
        {
            public override void OnAuthorization(HttpActionContext actionContext)
            {
                skipLogAttribute skiplogin = actionContext.ActionDescriptor.GetCustomAttributes<skipLogAttribute>().FirstOrDefault();
                if (skiplogin!=null)
                {
                    return;
                }
            
                AuthenticationHeaderValue headevalue = actionContext.Request.Headers.Authorization;
                if (headevalue != null)
                {
                    string Msg = string.Empty;
                    if (ValidateTicket(headevalue.Parameter,out Msg))
                    {
                        return;
                    }
                    else
                    {
                        this.HandlerUnAuthorization(Msg);
                    }
                }
                else {
                    this.HandlerUnAuthorization("请先获取登陆授权的Ticket");
                }
            }
            private void HandlerUnAuthorization(string Msg)
            {
                throw new Exception(Msg);
            }
    
            private bool ValidateTicket(string parameter,out string Msg)
            {
                Msg = string.Empty;
                if (!string.IsNullOrWhiteSpace(parameter))
                {
                    FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(parameter);
                    if (ticket != null)
                    {
                        if (ticket.Expired)
                        {
                            Msg = "接口时间已经过期,请重新登陆授权!";
                            return false;
                        }
                        if (string.Equals($"uid=zrf,pwd=123", ticket.UserData))// $"uid={accountID},pwd={pwd}"
                        {
                            Msg = "授权成功!";
                            return true;
                        }
                        else {
                            Msg = "授权失败,请重新登陆授权!";
                            return false;
                        }
                    }
                }
                return false;
            }
        }
    }
    

      

     

    6:自定义的特性,用来跳过权限的验证

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace WebApplication1.Filters
    {
    public class skipLogAttribute:Attribute
    {
    }
    }
    

      

     7:在WebApiConfig 文件中来注册一个全局的授权过滤器

    namespace WebApplication1.App_Start
    {
    using System.Web.Mvc;
    public static class WebApiConfig
    {
    public static void Register(HttpConfiguration config)
    {
    // Web API 配置和服务
    
    // Web API 路由
    config.MapHttpAttributeRoutes();
    config.Filters.Add(new Filters.CustomerAuthenrazationFilterAttribute());
    }
    }
    }
    

    8:最后上两张测试的截图: 

     

    最后,这个案例只是起到抛砖引玉的作用,大家还可以做得更加的细致及合理

    如下:

    我们还可以加上随机字符串:A;

    时间戳:B(时间精确到秒,方便后续判断,可过期);

    唯一的uid C;

    pwd D(根据uid来查询数据库并获取到pwd),;

    获取自定义的签名Sign:(如:uid+A+B+C+D 这4个值再MD5一下,防篡改),这样就和微信那套机制就差不多了! 嘻嘻!

    规则我们自己来定,欢迎大家提出有建议性的回复,谢谢

     

     

     

  • 相关阅读:
    xshell入门及Linux常用命令
    C++之vector
    c++ 之 string
    引用 与 指针
    关于时间复杂度的计算以及相关概念
    位运算
    thymeleafDemo
    面试总结
    关于mvvm原理实现,模拟vue(3)-----发布订阅
    关于mvvm原理实现,模拟vue(2)-----模板编译
  • 原文地址:https://www.cnblogs.com/Fengge518/p/11782262.html
Copyright © 2011-2022 走看看