我对ASP完全不熟悉。NET MVC堆栈,我想知道发生了什么简单的页面对象和请求ServerVariables对象?
基本上,我想拉出客户端PC的IP地址,但我不明白当前的MVC结构如何改变了这一切。
据我所知,大多数变量对象已经被HttpRequest变量所取代。
有人愿意分享一些资源吗?在ASP中有很多东西可以学习。NET MVC世界。:)
例如,我有一个带有当前函数的静态类。我如何得到相同的结果使用ASP。净MVC吗?
public static int getCountry(Page page)
{
return getCountryFromIP(getIPAddress(page));
}
public static string getIPAddress(Page page)
{
string szRemoteAddr = page.Request.ServerVariables["REMOTE_ADDR"];
string szXForwardedFor = page.Request.ServerVariables["X_FORWARDED_FOR"];
string szIP = "";
if (szXForwardedFor == null)
{
szIP = szRemoteAddr;
}
else
{
szIP = szXForwardedFor;
if (szIP.IndexOf(",") > 0)
{
string [] arIPs = szIP.Split(',');
foreach (string item in arIPs)
{
if (!isPrivateIP(item))
{
return item;
}
}
}
}
return szIP;
}
我如何从控制器页面调用这个函数?
简单的答案是使用HttpRequest。UserHostAddress财产。
示例:从控制器内部:
using System;
using System.Web.Mvc;
namespace Mvc.Controllers
{
public class HomeController : ClientController
{
public ActionResult Index()
{
string ip = Request.UserHostAddress;
...
}
}
}
示例:从helper类中:
using System.Web;
namespace Mvc.Helpers
{
public static class HelperClass
{
public static string GetIPHelper()
{
string ip = HttpContext.Current.Request.UserHostAddress;
..
}
}
}
但是,如果请求已经通过一个或多个代理服务器传递,则HttpRequest返回的IP地址。UserHostAddress属性将是中继请求的最后一个代理服务器的IP地址。
代理服务器可以使用事实标准,将客户端的IP地址放在X-Forwarded-For HTTP报头中。除了不能保证请求有X-Forwarded-For报头外,也不能保证X-Forwarded-For没有被欺骗。
原来的答案
Request.UserHostAddress
上面的代码提供了Client的IP地址,而不需要查找集合。Request属性在控制器(或视图)中可用。因此,你可以传递一个Request对象来获得相同的结果,而不是传递一个Page类给你的函数:
public static string getIPAddress(HttpRequestBase request)
{
string szRemoteAddr = request.UserHostAddress;
string szXForwardedFor = request.ServerVariables["X_FORWARDED_FOR"];
string szIP = "";
if (szXForwardedFor == null)
{
szIP = szRemoteAddr;
}
else
{
szIP = szXForwardedFor;
if (szIP.IndexOf(",") > 0)
{
string [] arIPs = szIP.Split(',');
foreach (string item in arIPs)
{
if (!isPrivateIP(item))
{
return item;
}
}
}
}
return szIP;
}
这里的许多代码都非常有用,但我根据自己的目的对其进行了清理,并添加了一些测试。这是我最后得出的结论:
using System;
using System.Linq;
using System.Net;
using System.Web;
public class RequestHelpers
{
public static string GetClientIpAddress(HttpRequestBase request)
{
try
{
var userHostAddress = request.UserHostAddress;
// Attempt to parse. If it fails, we catch below and return "0.0.0.0"
// Could use TryParse instead, but I wanted to catch all exceptions
IPAddress.Parse(userHostAddress);
var xForwardedFor = request.ServerVariables["X_FORWARDED_FOR"];
if (string.IsNullOrEmpty(xForwardedFor))
return userHostAddress;
// Get a list of public ip addresses in the X_FORWARDED_FOR variable
var publicForwardingIps = xForwardedFor.Split(',').Where(ip => !IsPrivateIpAddress(ip)).ToList();
// If we found any, return the last one, otherwise return the user host address
return publicForwardingIps.Any() ? publicForwardingIps.Last() : userHostAddress;
}
catch (Exception)
{
// Always return all zeroes for any failure (my calling code expects it)
return "0.0.0.0";
}
}
private static bool IsPrivateIpAddress(string ipAddress)
{
// http://en.wikipedia.org/wiki/Private_network
// Private IP Addresses are:
// 24-bit block: 10.0.0.0 through 10.255.255.255
// 20-bit block: 172.16.0.0 through 172.31.255.255
// 16-bit block: 192.168.0.0 through 192.168.255.255
// Link-local addresses: 169.254.0.0 through 169.254.255.255 (http://en.wikipedia.org/wiki/Link-local_address)
var ip = IPAddress.Parse(ipAddress);
var octets = ip.GetAddressBytes();
var is24BitBlock = octets[0] == 10;
if (is24BitBlock) return true; // Return to prevent further processing
var is20BitBlock = octets[0] == 172 && octets[1] >= 16 && octets[1] <= 31;
if (is20BitBlock) return true; // Return to prevent further processing
var is16BitBlock = octets[0] == 192 && octets[1] == 168;
if (is16BitBlock) return true; // Return to prevent further processing
var isLinkLocalAddress = octets[0] == 169 && octets[1] == 254;
return isLinkLocalAddress;
}
}
下面是一些针对该代码的NUnit测试(我使用Rhino mock来模拟HttpRequestBase,这是下面的M<HttpRequestBase>调用):
using System.Web;
using NUnit.Framework;
using Rhino.Mocks;
using Should;
[TestFixture]
public class HelpersTests : TestBase
{
HttpRequestBase _httpRequest;
private const string XForwardedFor = "X_FORWARDED_FOR";
private const string MalformedIpAddress = "MALFORMED";
private const string DefaultIpAddress = "0.0.0.0";
private const string GoogleIpAddress = "74.125.224.224";
private const string MicrosoftIpAddress = "65.55.58.201";
private const string Private24Bit = "10.0.0.0";
private const string Private20Bit = "172.16.0.0";
private const string Private16Bit = "192.168.0.0";
private const string PrivateLinkLocal = "169.254.0.0";
[SetUp]
public void Setup()
{
_httpRequest = M<HttpRequestBase>();
}
[TearDown]
public void Teardown()
{
_httpRequest = null;
}
[Test]
public void PublicIpAndNullXForwardedFor_Returns_CorrectIp()
{
// Arrange
_httpRequest.Stub(x => x.UserHostAddress).Return(GoogleIpAddress);
_httpRequest.Stub(x => x.ServerVariables[XForwardedFor]).Return(null);
// Act
var ip = RequestHelpers.GetClientIpAddress(_httpRequest);
// Assert
ip.ShouldEqual(GoogleIpAddress);
}
[Test]
public void PublicIpAndEmptyXForwardedFor_Returns_CorrectIp()
{
// Arrange
_httpRequest.Stub(x => x.UserHostAddress).Return(GoogleIpAddress);
_httpRequest.Stub(x => x.ServerVariables[XForwardedFor]).Return(string.Empty);
// Act
var ip = RequestHelpers.GetClientIpAddress(_httpRequest);
// Assert
ip.ShouldEqual(GoogleIpAddress);
}
[Test]
public void MalformedUserHostAddress_Returns_DefaultIpAddress()
{
// Arrange
_httpRequest.Stub(x => x.UserHostAddress).Return(MalformedIpAddress);
_httpRequest.Stub(x => x.ServerVariables[XForwardedFor]).Return(null);
// Act
var ip = RequestHelpers.GetClientIpAddress(_httpRequest);
// Assert
ip.ShouldEqual(DefaultIpAddress);
}
[Test]
public void MalformedXForwardedFor_Returns_DefaultIpAddress()
{
// Arrange
_httpRequest.Stub(x => x.UserHostAddress).Return(GoogleIpAddress);
_httpRequest.Stub(x => x.ServerVariables[XForwardedFor]).Return(MalformedIpAddress);
// Act
var ip = RequestHelpers.GetClientIpAddress(_httpRequest);
// Assert
ip.ShouldEqual(DefaultIpAddress);
}
[Test]
public void SingleValidPublicXForwardedFor_Returns_XForwardedFor()
{
// Arrange
_httpRequest.Stub(x => x.UserHostAddress).Return(GoogleIpAddress);
_httpRequest.Stub(x => x.ServerVariables[XForwardedFor]).Return(MicrosoftIpAddress);
// Act
var ip = RequestHelpers.GetClientIpAddress(_httpRequest);
// Assert
ip.ShouldEqual(MicrosoftIpAddress);
}
[Test]
public void MultipleValidPublicXForwardedFor_Returns_LastXForwardedFor()
{
// Arrange
_httpRequest.Stub(x => x.UserHostAddress).Return(GoogleIpAddress);
_httpRequest.Stub(x => x.ServerVariables[XForwardedFor]).Return(GoogleIpAddress + "," + MicrosoftIpAddress);
// Act
var ip = RequestHelpers.GetClientIpAddress(_httpRequest);
// Assert
ip.ShouldEqual(MicrosoftIpAddress);
}
[Test]
public void SinglePrivateXForwardedFor_Returns_UserHostAddress()
{
// Arrange
_httpRequest.Stub(x => x.UserHostAddress).Return(GoogleIpAddress);
_httpRequest.Stub(x => x.ServerVariables[XForwardedFor]).Return(Private24Bit);
// Act
var ip = RequestHelpers.GetClientIpAddress(_httpRequest);
// Assert
ip.ShouldEqual(GoogleIpAddress);
}
[Test]
public void MultiplePrivateXForwardedFor_Returns_UserHostAddress()
{
// Arrange
_httpRequest.Stub(x => x.UserHostAddress).Return(GoogleIpAddress);
const string privateIpList = Private24Bit + "," + Private20Bit + "," + Private16Bit + "," + PrivateLinkLocal;
_httpRequest.Stub(x => x.ServerVariables[XForwardedFor]).Return(privateIpList);
// Act
var ip = RequestHelpers.GetClientIpAddress(_httpRequest);
// Assert
ip.ShouldEqual(GoogleIpAddress);
}
[Test]
public void MultiplePublicXForwardedForWithPrivateLast_Returns_LastPublic()
{
// Arrange
_httpRequest.Stub(x => x.UserHostAddress).Return(GoogleIpAddress);
const string privateIpList = Private24Bit + "," + Private20Bit + "," + MicrosoftIpAddress + "," + PrivateLinkLocal;
_httpRequest.Stub(x => x.ServerVariables[XForwardedFor]).Return(privateIpList);
// Act
var ip = RequestHelpers.GetClientIpAddress(_httpRequest);
// Assert
ip.ShouldEqual(MicrosoftIpAddress);
}
}