构建 Owin 中间件 来获取客户端IP地址
Not so long ago, we discussed on this blog the possible ways of retrieving the client’s IP address in ASP.NET Web API.
With the latest changes in the Web API 2 infrastructure, and the emergence of Owin and the Katana project as the common glue between the underlying host and the web framework(s) running on it, it’s becoming natural to move these types of application-wide concerns (security, logging etc) to Owin middleware.
Let’s have a look at how you could – as an introductory example – obtain client’s IP address at the Owin middleware level, and why is it beneficial.
The benefits of Owin
We’ll not really go into the basic details of Owin here – I have already covered that in previous posts – so let’s just say that the gist is that with Owin we can easily host a number of frameworks side by side and decouple our web frameworks from the host beneath it. Naturally, through Owin middleware, we can address common concerns in a single place too – the most obvious usage being security.
If you are used to working with HttpMessageHandlers, the idea behind OWIN middleware is very similar – as they are chained one after another and allow you to modify the incoming request or outgoing response.
For quite a while, working with OWIN middleware meant dealing with quite a raw API, as you’d have to handle constructs such as Func<idictionary<string, object="">, Task>.
Now, Microsoft.Owin.dll provides a base abstract class for creating Owin middleware easily:
public abstract class OwinMiddleware
{
protected OwinMiddleware(OwinMiddleware next);
protected OwinMiddleware Next { get; set; }
public abstract Task Invoke(OwinRequest request, OwinResponse response);
}
With that in place, it’s almost like implementing a MessageHandler.
Getting started with IP example
To get started we’ll need a new console project and following packages:
- – Katana: install-package Microsoft.Owin.Hosting -pre
- – Katana Http Listener: install-package Microsoft.Owin.Host.HttpListener -pre
- – Web API adapter: install-package Microsoft.AspNet.WebApi.Owin -pre
These 3 packages will bring in some additional dependencies they have.
We can now start a simple Owin server with Web API host – this is nothing new and should be very straight forward.
class Program
{
static void Main(string[] args)
{
string uri = "http://localhost:999/";
using (WebApp.Start<Startup>(uri))
{
Console.WriteLine("Started");
Console.ReadKey();
Console.WriteLine("Stopped");
}
}
} public class Startup
{
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
app.UseWebApi(config);
}
} public class TestController : ApiController
{
public string Get()
{
return "Hello world!";
}
}
So really just a simple Web API Test controller and a setup to wire it all together.
Adding Owin middleware for IP inspection
Now suppose you’d like to restrict specific IP addresses.
If we do it at Owin level, it would affect all the frameworks running in your process (perhaps you might want to add SignalR or NancyFx) – so sounds like a perfect place to do it, doesn’t it?
Well, it’s extremely easy. We simply inherit from OwinMiddleware class and implement the Invoke method.
public class IpMiddleware : OwinMiddleware
{
private readonly HashSet<string> _deniedIps; public IpMiddleware(OwinMiddleware next, HashSet<string> deniedIps) :
base(next)
{
_deniedIps = deniedIps;
} public override async Task Invoke(OwinRequest request, OwinResponse response)
{
var ipAddress = (string)request.Environment["server.RemoteIpAddress"]; if (_deniedIps.Contains(ipAddress))
{
response.StatusCode = 403;
return;
} await Next.Invoke(request, response);
}
}
In this case, we also pass in the list of restricted IPs. When we add our middleware to the pipeline, we are allowed to pass in params object[] so we can send whatever we want into our middleware constructor (more on that in a second).
We can retrieve the client’s IP address by asking for server.RemoteIpAddress key of the Environment object on the OwinRequest – it’s an IDictionary<string, object=""> and contains everything that could be interesting for us.
Based on that we can either deny the request (let’s say send a 403 Forbidden status code), otherwise we continue on to the next middleware.
To plug this in we need to add the following in the Configuration method of the Startup class – notice that this is the moment that we can send in any params to the Middleware too:
var deniedIps = new HashSet<string> {"192.168.0.100", "192.168.0.101"}; //whatever
app.Use(typeof(IpMiddleware), deniedIps);
Also, we want to add it before the call to setup Web API!
Trying it out
Now if we access from a client that’s allowed to see the API, he gets the correct response as expected:

If the client is restricted, we reply with the 403 directly from the middleware:

构建 Owin 中间件 来获取客户端IP地址的更多相关文章
- C# WebApi 获取客户端ip地址
转自:http://www.cnblogs.com/weixing/p/5674078.html References required: HttpContextWrapper - System.We ...
- 在Thinkphp3.2.3框架下实现自动获取客户端IP地址的get_client_ip()函数
在Thinkphp框架下使用get_client_ip()函数获取客户端IP地址十分方便: 一行代码便可以实现:$ip = get_client_ip(); 但当我们测试时会遇到后台获取的IP地址显示 ...
- JAVA获取客户端IP地址
在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的.但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实I ...
- (转)【ASP.NET开发】获取客户端IP地址 via C#
[ASP.NET开发]获取客户端IP地址 via C# 说明:本文中的内容是我综合博客园上的博文和MSDN讨论区的资料,再通过自己的实际测试而得来,属于自己原创的内容说实话很少,写这一篇是为了记录自己 ...
- php获取客户端ip地址
本文介绍一个,php获取客户端的IP地址的实例代码,有需要的朋友参考下吧. 获取客户端IP地址的代码,如下: 复制代码代码示例: <?php//取得客户端IP的函数function get_cl ...
- 获取客户端IP地址 via C#
获取客户端IP地址 via C# 说明:本文中的内容是我综合博客园上的博文和MSDN讨论区的资料,再通过自己的实际测试而得来,属于自己原创的内容说实话很少,写这一篇是为了记录自己在项目中做过的事情,同 ...
- thinkphp 获取客户端ip地址方法
/** * 获取客户端IP地址 * @param integer $type 返回类型 0 返回IP地址 1 返回IPV4地址数字 * @param boolean $adv 是否进行高级模式获取(有 ...
- 获取客户端IP地址定位城市信息
获取客户端IP地址定位城市信息 1.首先获取客户端的IP地址 function getIPaddress(){ $IPaddress=''; if (isset($_SERVER)){ if (iss ...
- Tp框架获取客户端IP地址
/** * 获取客户端IP地址 * @param integer $type 返回类型 0 返回IP地址 1 返回IPV4地址数字 * @return mixed */ function get_cl ...
随机推荐
- error $GOPATH: no library found in $GOPATH: rdkafka
安装confluent-kafka-go出错时,请使用brew安装pkg-config,手动go get安装的pkg-config还不行... 错误提示: go get -u github.com/c ...
- List分组
IEnumerable<IGrouping<string, SysMap>> query = sysMapList.GroupBy(pet => pet.Mobile);
- tracert traceroute
二者都用于探测数据包从源到目的经过路由的IP,但两者探测的方法却有差别.不同点:一.应用环境不同tracert是应用在windows下.traceroute则是应用在linux/BSD/router/ ...
- Mysql推荐使用规范(转)
一:基础规范 1.使用InnoDB存储引擎 支持事务.行级锁.并发性能更好.CPU及内存缓存页优化使得资源利用率更高 2.推荐使用utf8mb4字符集 无需转码,无乱码风险, 支持emoji表情以及部 ...
- Cocoapods 创建自己的公开库、私有库
如何创建自己的共有库 1.注册Trunk trunk需要CocoaPods 0.33版本以上,用pod --version 命令查看版本 CocoaPods版本 如果版本低,需要升级: sudo ge ...
- PHP 通过构造器进行依赖注入 demo
class A{ public $b; public $f; function __construct( B $b , $f = 1 ){ $this->b = $b; $this->f ...
- 关于linux - Centos 7 下DHCP服务的安装与配置
DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)是一个局域网的网络协议,使用UDP协议工作, 主要有两个用途:给内部网络或网络服务供应商自动分配IP ...
- Spring Security http标签的use-expressions="true"属性
如果声明为true,那么在access属性要用hasRole()这样写: <intercept-url pattern="/secure/extreme/**" access ...
- 12.vue属性.监听.组件
1.计算属性 https://cn.vuejs.org/v2/guide/computed.html new Vue({ computed:{//定义 show(){ } } }) ++计算属性1.h ...
- vue的单向数据流
父级向子组件传递的值, 子组件不能直接修改这个穿过来的值,否则会曝出警告,这就是单项数据流. 如果是引用值,传递的是引用值得地址,而不是值本身,也就是说,子组件里修改这个传过来的值,通常的做法是放到它 ...