• asp.net mvc4 之Webapi之客户端或服务器端安全控制


    一、WebAPI的工作方式

    WebAPI的工作方式:HTTP的请求最先是被传递到HOST中的,如果WebAPI是被寄宿在IIS上的,这个HOST就是IIS上,HOST是没有能力也没有必 要进行请求的处理的,请求通过HOST被转发给了HttPServer此时已经进入WebAPI的处理加工范围,HttpServer是 System.Net.HTTP中的一个类,通过HttpServer,请求被封装成了WebAPI中的请求承载 类:HttpRequestMessage,这个封装后的请求可以经过一系列自定义的Handler来处理,这些handler串联成一个 pipeline,最后请求会被传递给HttpControlDispather,这个类通过对路由表的检索来确定请求将被转发到的具体的 Controller中的Action。

    由此我们早就可以看出,想要解决第二个问题,可以直接在Handler PipeLine中进行,这种AOP风格的过滤器(拦截器)在REST的Webservice的安全验证中应用很广,一般大家比较乐于在HTTP头或者在 HTTP请求的URL中加上身份验证字段进行身份验证,下面举一个在Http头中添加身份验证信息的小例子:

    二、说明

    本节所使用的例子,只是在“asp.net mvc4 webapi之应用客户端访问服务器端”的例子上稍作修改而已,在看本篇文章之前,请先看文档“asp.net mvc4 webapi之应用客户端访问服务器端”

    三、例子修改

    首先打开文档“webapi之应用客户端访问服务器端.docx”中对应的解决方案“MyTest”,下面分别介绍我们对服务器端、客户端所做的修改

    1、服务器端

    (1)、首先添加一个文件夹,命名为:HandlerLib

    (2)、在文件夹HandlerLib添加一个类,并命名为:SecurityHandler,代码如下

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Net;

    using System.Net.Http;

    using System.Threading.Tasks;

    using System.Web;

     

    namespace MyServer.HandlerLib

    {

        public class SecurityHandler : DelegatingHandler

        {

            protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken

               cancellationToken)

            {

                int matchHeaderCount = request.Headers.Count((item) =>

                {

                    if ("keyword".Equals(item.Key))

                    {

                        foreach (var str in item.Value)

                        {

                            //wanli就是约定的服务器端验证口令或验证验证信息

                            if ("wanli".Equals(str))

                            {

                                return true;

                            }

                        }

                    }

                    return false;

                });

                if (matchHeaderCount > 0)

                {

                    return base.SendAsync(request, cancellationToken);

                }

                return Task.Factory.StartNew<HttpResponseMessage>(() => { return new HttpResponseMessage(HttpStatusCode.Forbidden); });

            }

        }

     

    }

     

    (3)、添加

    注:代码的处理逻辑很简单:如果身份验证码匹配成功,则通过base.SendAsync继续将请求向下传递,否则返回直接中断请求的传递,直接返回一个响应码为403的响应,指示没有权限。
    注意由于SendAsync的返回值需要封装在Task之中,所以需要使用Task.Factory.StartNew将返回值包含在Task中

    将SecurityHandler注入到HOST中
    本例中WebAPI HOST在IIS上,所以我们只需将我们定义的SecurityHandler在Application_Start中定义即可

            protected void Application_Start()

            {

                //省略其他逻辑代码

                GlobalConfiguration.Configuration.MessageHandlers.Add(new SecurityHandler ());

            }

    由于WebAPI Host在IIS上,所以HttpServer和HttpControllerDispatcher不用我们手工处理

    2、客户端的修改

    添加类RequestCheckHandler.cs,其代码如下:

    客户端的RequestCheckHandler用于将身份验证信息添加入报头

    class RequestCheckHandler : DelegatingHandler

    {

            protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)

            {

                request.Headers.Add("keyword", "wanli");

                return base.SendAsync(request, cancellationToken);

            }

    }

    注:
    1. RequestCheckHandler继承自DelegatingHandler类,上面已经说过,WebAPI的客户端和服务端被设计为相互对应的两套结构,所以不论是在客户端还是服务端,RequestCheckHandler都是继承自DelegatingHandler类
    2.DelegatingHandler的sendAsync方法便是处理请求和接受请求时会被调用的方法,该方法返回值是HttPResponseMessage,接收的值为HttpRequestMessage,符合我们的一般认知
    3.方法的最后,调用base.SendAsync是将Request继续向该pipeline的其他RequestCheckHandler传递,并获取其返回值。由于该方法不包含Response的处理逻辑,只需直接将上一个RequestCheckHandler的返回值直接返回

     

     

    客户端的form1.cs窗体的后台代码修改为

    using System;

    using System.Collections.Generic;

    using System.ComponentModel;

    using System.Data;

    using System.Drawing;

    using System.Linq;

    using System.Net.Http;

    using System.Text;

    using System.Threading.Tasks;

    using System.Windows.Forms;

     

    namespace MyClient

    {

        public partial class Form1 : Form

        {

            public Form1()

            {

                InitializeComponent();

            }

     

            private void btnSubmit_Click(object sender, EventArgs e)

            {

                string userName = txName.Text.Trim();

                string passWord = txPwd.Text.Trim();

                string url = @"http://localhost:8748/api/User/GetUserInfo?userName=" + userName + "&passWord="+passWord;

     

                HttpClient client = new HttpClient(new RequestCheckHandler() { InnerHandler = new HttpClientHandler() });

                HttpResponseMessage response = client.GetAsync(url).Result;      

                string str=  response.Content.ReadAsStringAsync().Result;

                MessageBox.Show(str);

            }

        }

    }

     

    客户端的主程序创建了一个HttpClient,HttpClient可以接受一个参数,该参数就是CustomHandler,此处我们嵌入了我们定义的 RequestUpHandler,用于对Request报头进行嵌入身份验证码的处理,CustomHandler通过InnerHandler属性嵌 入其内置的下一个CustomHandler,此处,由于没有下一个CustomerHandler,我们直接嵌入HttpClientHandler用 于将HttpRequestMessage转化为HTTP 请求、将HTTP响应转化为HttpResponseMessage

  • 相关阅读:
    第一周例行报告
    2018091-2 博客作业
    jQuery $.post $.ajax用法
    HTML ul、li 属性介绍
    PHP日期格式转时间戳
    php字符串与字符替换函数
    Linux内核参数
    ifconfig-dropped
    mysql_load_data及权限管理
    加快mysql导入导出速度
  • 原文地址:https://www.cnblogs.com/net064/p/8681622.html
Copyright © 2020-2023  润新知