Web Api 安全

159 篇文章 3 订阅

过去,我写过一两个Web Api,没有任何身份校验和安全措施,随便在浏览器中输入地址就能访问,谁都可以。无异于裸奔。

有关Web Api的安全措施,我目前了解到的有以下一些:

一、使用Basic Authentication验证用户
客户端在发送Http请求的时候在Header部分提供一个基于Base64编码的用户名和密码,形式为“username:password”,消息接收者(服务器)进行验证,通过后继续处理请求。

这里写图片描述

实现方法:
1、定义一个安全特性”ApiAuthorizeAttribute”

using System;
using System.Net;
using System.Net.Http;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Web.Http.Filters;

namespace WebApi
{
    public class ApiAuthorizeAttribute : AuthorizationFilterAttribute
    {

        public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            //forms authentication Case that user is authenticated using forms authentication//so no need to check header for basic authentication.
            if (Thread.CurrentPrincipal.Identity.IsAuthenticated)
            {
                return;
            }

            var authHeader = actionContext.Request.Headers.Authorization;

            if (authHeader != null)
            {
                if (authHeader.Scheme.Equals("basic", StringComparison.OrdinalIgnoreCase) &&
                    !String.IsNullOrWhiteSpace(authHeader.Parameter))
                {
                    var credArray = GetCredentials(authHeader);
                    var userName = credArray[0];
                    var password = credArray[1];

                    //if (IsResourceOwner(userName, actionContext))
                    if(isCheckOK(userName,password))
                    {
                        //You can use Websecurity or asp.net memebrship provider to login, for
                        //for he sake of keeping example simple, we used out own login functionality
                        //if (TheRepository.LoginStudent(userName, password))
                        {
                            var currentPrincipal = new GenericPrincipal(new GenericIdentity(userName), null);
                            Thread.CurrentPrincipal = currentPrincipal;
                            return;
                        }
                    }
                }
            }

            HandleUnauthorizedRequest(actionContext);
        }
        private bool isCheckOK(string username,string pwd)
        {//这里我只是简单做个判断;可以引入数据库操作做一般意义上的校验
            return (username == "chenqu");
        }
        private string[] GetCredentials(System.Net.Http.Headers.AuthenticationHeaderValue authHeader)
        {

            //Base 64 encoded string
            var rawCred = authHeader.Parameter;
            var encoding = Encoding.GetEncoding("iso-8859-1");
            var cred = encoding.GetString(Convert.FromBase64String(rawCred));

            var credArray = cred.Split(':');

            return credArray;
        }

        private bool IsResourceOwner(string userName, System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            var routeData = actionContext.Request.GetRouteData();
            var resourceUserName = routeData.Values["userName"] as string;

            if (resourceUserName == userName)
            {
                return true;
            }
            return false;
        }

        private void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);

            actionContext.Response.Headers.Add("WWW-Authenticate",
                                               "Basic Scheme='eLearning' location='http://localhost:8323/account/login'");

        }
    }
}

2、Web Api的controller或action上应用安全特性”ApiAuthorizeAttribute”

namespace WebApi.Areas.Test.Controllers
{
    public class Test1Controller : ApiController
    {
        [ApiAuthorize]
        public string Get(int id)
        {
            return "Hello World! Hello Human!";
        }
    }
}

二、https
由于在Basic Authentication验证用户方式中,用户名和密码仅适用base64编码,因此为了保证安全性,basic authentication通常是基于SSL连接(https)。

将一个网站设置成支持https协议很简单,以IIS为例:
这里写图片描述

这里写图片描述

这里写图片描述

一定要绑定一个证书,否则会无法访问。

另外,https这里绑定的端口是443(默认),那么地址
https://testweb/webapi/api/test/test1/1 相当于
https://testweb:443/webapi/api/test/test1/1
我有一次因为创建了一个本地网站,端口是8000,然后支持https,思维定式地认为访问地址是:https://testweb:8000/,结果提示404。https可不是单纯地在http后面加个s而已,是两种不同的协议,分别有自己对应的端口。

有关这个https,证书,服务器端证书,客户端证书,是另外一个主题。

三、如何访问这些Web Api?
既然是Web Api,并非是在浏览器地址里输入进行访问的,主要还是在程序里调用。
以C#为例。客户端:

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        static readonly Encoding UTF8 = Encoding.GetEncoding("utf-8");
        private void button1_Click(object sender, EventArgs e)
        {
            using (WebClient webClient = new WebClient())
            {
                ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
                webClient.Encoding = UTF8;
                webClient.Credentials = new NetworkCredential("chenqu", "123456");

MessageBox.Show(webClient.DownloadString("https://localhost/webapi/api/test/test1/1"));
            }
        }
    }

这里写图片描述

参考文章:
Web Api的安全性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值