构建 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 ...
随机推荐
- 自定义命令杀死 java 进程 alias kjava
alias kjava='ps -ef|grep ProcessName |awk "{print $2}"|xargs kill -9' 上面脚本放在杀JAVA进程中,会出现一些 ...
- Kafka Eagle Consumers不显示
原因: kafka.eagle.offset.storage配置有误 该配置的作用:# kafka offset storage -- Offset stored in a Kafka cluster ...
- Java锁机制(一)synchronized
进行多线程编程的时候,需要考虑的是线程间的同步问题.对于共享的资源,需要进行互斥的访问.在Java中可以使用一些手段来达到线程同步的目的: 1. synchronized 2. ThreadLocal ...
- 转:十步完全理解SQL
来自:http://blog.jobbole.com/55086/ 很多程序员视 SQL 为洪水猛兽.SQL 是一种为数不多的声明性语言,它的运行方式完全不同于我们所熟知的命令行语言.面向对象的程序语 ...
- python中基本类型的连接组合和互相转换
本篇总结了一下字符串,列表,字典,元组的连接组合使用和类型的互相转换小例子,尤其列表中的extend()方法和字典中的 update方法非常的常用. 1.连接两个字符串 a = "hello ...
- Delphi过程函数传递参数的几种方式
Delphi过程函数传递参数的几种方式 在Delphi过程.函数中传递参数几个修饰符为Const.Var.Out. 另一种不加修饰符的为默认按值传递参数. 一.默认方式以值方式传递参数 proced ...
- [LeetCode] Bomb Enemy 炸弹人
Given a 2D grid, each cell is either a wall 'W', an enemy 'E' or empty '0' (the number zero), return ...
- hibernate08--OpenSessionInView
创建一个web项目,然后生成HibernateSessionFactory文件! package cn.bdqn.util; import org.hibernate.HibernateExcepti ...
- hibernate的merge()
映射文件中的主键如果用sequence序列,需要指定序列名,如果不指定,则会自动使用hibernate_sequence(需要自己创建) getCurrentSession()方法获得的session ...
- 给table加边框的样式
<style> .tb { width: 1600px; text-align: center; border-collapse: collapse; } .tb tr td { bord ...