Web API身份认证解决方案之Basic基础认证

 更新时间:2022年03月13日 11:33:45   作者:.NET开发菜鸟  
本文详细讲解了Web API身份认证解决方案之Basic基础认证,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

一、WebApi中为什么需要身份认证

我们在使用WebApi的时候,都是通过URL去获取数据。也就是说,任何人只要知道了URL地址,就能随意的访问后台的服务接口,就可以访问或者修改数据库数据了,这样就会导致很严重的后果。

1、我们不加身份认证,匿名用户可以直接通过url随意访问接口:

2、增加了身份认证之后,只有带了票据的请求才能访问对应的接口。

二、常见的认证方式

WebApi中常见的认证方式有如下几种:

  • FORM身份验证
  • 集成WINDOWS验证
  • Basic基础认证
  • Digest摘要认证

三、Basic基础认证

Basic基础认证原理

Basic认证的基本原理就是加密用户信息生成Ticket,每次请求后端API接口的时候把生成的Ticket信息加到http请求的头部传给后端进行验证。具体步骤如下:

  • 1、登录的时候验证用户名和密码,如果验证通过,则将用户名和密码按照一定的规则生成加密后的票据信息Ticket,然后将Ticket传递到前端。
  • 2、如果登录成功,前端定义一个全局的变量接收API接口返回的Ticket信息。
  • 3、前端界面再次发起ajax请求后端API接口的时候,将Ticket信息加入到HTTP请求的Head里面,将Ticket信息随着http请求一起发送到后端API接口。
  • 4、在后端的WebApi服务中定义一个类,该类继承自AuthorizeAttribute类,然后重新父类里面的OnAuthorization方法,在OnAuthorization方法里面,通过actionContext参数取得http请求的Head,从Head里面可以获取前端传递过来的Ticket信息。将Ticket解密得到用户名和密码,然后验证用户名和密码是否正确。如果正确,表示验证通过。如果不正确,则返回401未授权的错误。

四、Basic基础认证示例代码

假设我们要访问Users控制器的Get接口,该接口方法返回int类型的List集合。

1、登录的API接口

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Security;
using WebApiBasicAuthorize.CustomerAttribute;
using WebApiBasicAuthorize.Entity;

namespace WebApiBasicAuthorize.Controllers
{
    [BasicAuthorize]
    public class UsersController : ApiController
    {
        /// <summary>
        /// 允许匿名登录
        /// </summary>
        /// <param name="account"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpGet]
        public IHttpActionResult Login(string account,string password)
        {
            ReturnValueEntity entity = new ReturnValueEntity();
            // 真实生产环境中要去数据库校验account和password
            if (account.ToUpper().Trim().Equals("ADMIN") && password.Trim().Equals("123456"))
            {
                FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(0, account, DateTime.Now,
                    DateTime.Now.AddHours(1), true, string.Format("{0}&{1}", account, password),
                    FormsAuthentication.FormsCookiePath);
                var result = new { Result = true, Ticket = FormsAuthentication.Encrypt(ticket) };
                entity.Result = true;
                entity.Ticket = FormsAuthentication.Encrypt(ticket);
            }
            else
            {
                entity.Result = false;
                entity.Ticket = "";
            }
            return Json<ReturnValueEntity>(entity);
        }

        [HttpGet]
        public IHttpActionResult Get()
        {
            List<int> list = new List<int>();
            list.Add(1);
            list.Add(2);
            list.Add(3);
            list.Add(4);
            list.Add(5);
            return Json<List<int>>(list);
        }
    }
}

在Login方法上面添加 [AllowAnonymous]特性,表示允许匿名登录。

2、基础认证接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Security;

namespace WebApiBasicAuthorize.CustomerAttribute
{
    /// <summary>
    ///  自定义特性继承自AuthorizeAttribute
    /// </summary>
    public class BasicAuthorizeAttribute:AuthorizeAttribute
    {
        public override void OnAuthorization(HttpActionContext actionContext)
        {
            // 从当前http请求Request对象的头部信息里面获取Authorization属性
            var authorization = actionContext.Request.Headers.Authorization;
            // 判断控制器获取action方法上面是否有AllowAnonymousAttribute特性,如果有,则允许匿名登录
            if (actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>(true).Count != 0
                || actionContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes<AllowAnonymousAttribute>(true).Count != 0)
            {
                base.OnAuthorization(actionContext);
            }
            else if (authorization != null && authorization.Parameter != null)
            {
                // 验证用户逻辑
                if (ValidateTicket(authorization.Parameter))
                {
                    // 验证通过
                    base.IsAuthorized(actionContext);
                }
                else
                {
                    this.HandleUnauthorizedRequest(actionContext);
                }
            }
            else
            {
                // 返回401没有授权的状态码
                this.HandleUnauthorizedRequest(actionContext);
            }

        }

        /// <summary>
        /// 验证Ticket信息
        /// </summary>
        /// <param name="encryptTicket"></param>
        /// <returns></returns>
        private bool ValidateTicket(string encryptTicket)
        {
            // 解密Ticket
            var strTicket = FormsAuthentication.Decrypt(encryptTicket).UserData;
            // 从Ticket里面获取用户名和密码
            int index = strTicket.IndexOf("&");
            //string strUser=strTicket
            string[] array = strTicket.Split('&');
            string strUser = array[0];
            string strPwd = array[1];
            // 真实生产环境中应该用解密的用户名和密码去数据库验证,这里为了演示方便
            // 假定用户名是Admin,密码是123456
            if(strUser.Equals("Admin")&&strPwd.Equals("123456"))
            {
                return true;
            }
            else
            {
                return false;
            }           
        }
    }
}

3、前端代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>权限认证</title>
    <script src="jquery-1.10.2.min.js"></script>
    <script>
        // 定义全局的ticket变量,用来保存登录成功以后的Ticket值
        var ticket;
       window.onload=function(){
            
       };
 
       function Login(){
           $.ajax({
               url:"http://localhost:20033/api/users?account="+$("#acc").val().trim()+"&password="+$("#pwd").val().trim(),
               type:"Get",
               dataType:"json",
               "headers": {
                "Content-Type": "application/json",
                "cache-control": "no-cache"
              },
               success:function(data){
                   if(result.Result){
                       ticket=data.Ticket;
                   }else{
                       alert("失败");
                   }
               },
               error:function(data){
                   alert(data);
               }
           });
       };
 
       function Test(){
           alert(ticket);
           $.ajax({
               url:'http://localhost:20033/api/users',
               type:"Get",
               dataType:"json",
               beforeSend:function(XHR){
                   //发送ajax请求之前向http的head里面加入验证信息
                   XHR.setRequestHeader('Authorization','BasicAuth '+ticket);
               },
               success:function(data){
                   alert(data);
               },
               error:function(data){
                   alert(data);
               }
 
           });
 
       };
    </script>
</head>
 
<body>
    <div>
        <div>
                <label>用户名:</label>
                <input type="text" id="acc">
        </div>
        <div>
                <label>密码:</label>
                <input type="password" id="pwd">
        </div>
        <div>
                <input type="button" id="btnLogin" onclick="Login()" value="登录">
        </div>
        <div>
            <input type="button" id="GetAccount" onclick="Test()" value="测试">
        </div>
    </div>
</body>
</html>

这里需要说明的是,我们在发送ajax请求之前,通过XHR.setRequestHeader('Authorization', 'BasicAuth ' + Ticket); 这句向http请求的Head里面添加Ticket信息。

通过上面的几步就可以达到Basic认证的效果了。

注意:后端的WebApi接口要配置允许跨域访问。

4、优化

每增加一个控制器,都需要在相应的控制器上面加[BasicAuthorize]特性,可以定义一个公共的控制器父类,该父类继承自ApiController,然后其他控制器继承该父类。

到此这篇关于Web API身份认证解决方案之Basic基础认证的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • asp.net core 修改默认端口的几种方法

    asp.net core 修改默认端口的几种方法

    这篇文章主要介绍了asp.net core 修改默认端口的几种方法,文中讲解非常详细,代码和图片帮助大家更好的理解,感兴趣的朋友可以了解下
    2020-06-06
  • asp.net Web.config 详细配置说明

    asp.net Web.config 详细配置说明

    asp.net开发的朋友,经常用得到web.config文件的配置,所以我们特整理了中文说明。
    2009-06-06
  • 利用Asp.Net Core的MiddleWare思想如何处理复杂业务流程详解

    利用Asp.Net Core的MiddleWare思想如何处理复杂业务流程详解

    这篇文章主要给大家介绍了关于利用Asp.Net Core的MiddleWare思想如何处理复杂业务流程的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起看看吧
    2018-08-08
  • Linux(Ubuntu)下搭建ASP.NET Core环境

    Linux(Ubuntu)下搭建ASP.NET Core环境

    本文给大家介绍的是无需安装mono,在Linux(Ubuntu14.04.4 LTS)下搭建ASP.NET Core环境 继续.NET跨平台,希望对大家能够有所帮助。
    2016-07-07
  • .NET实现Repeater控件+AspNetPager控件分页

    .NET实现Repeater控件+AspNetPager控件分页

    本文给大家分享的2个示例,演示AspNetPager最基本的功能,帮助您认识AspNetPager分页控件及了解它的工作原理。有需要的小伙伴可以参考下
    2015-11-11
  • .net GridView分页模板的实例代码

    .net GridView分页模板的实例代码

    .net GridView分页模板的实例代码,对分页代码有兴趣的朋友可以参考一下
    2013-03-03
  • ASP.NET MVC 3仿Server.Transfer效果的实现方法

    ASP.NET MVC 3仿Server.Transfer效果的实现方法

    这篇文章主要介绍了ASP.NET MVC 3仿Server.Transfer效果的实现方法,需要的朋友可以参考下
    2015-10-10
  • C#中OpenFileDialog和PictrueBox的用法分析

    C#中OpenFileDialog和PictrueBox的用法分析

    这篇文章主要介绍了C#中OpenFileDialog和PictrueBox的用法,以实例的形式较为详细的分析了OpenFileDialog和PictrueBox使用时的注意事项与具体用法,具有一定的参考借鉴价值,需要的朋友可以参考下
    2014-11-11
  • ASP.net(C#)实现简易聊天室功能

    ASP.net(C#)实现简易聊天室功能

    这篇文章主要为大家详细介绍了ASP.net实现简易聊天室功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • 浅谈ASP.NET Core的几种托管方式

    浅谈ASP.NET Core的几种托管方式

    这篇文章主要介绍了浅谈ASP.NET Core的几种托管方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12

最新评论