根据IP将用户重定向到子域
Posted
技术标签:
【中文标题】根据IP将用户重定向到子域【英文标题】:Redirect User to sub domain based on IP 【发布时间】:2016-08-24 07:40:01 【问题描述】:我正在尝试根据用户的 IP 地址位置将用户重定向到子域。我有一个页面加载观察器,它在每个请求上运行一个函数,它获取用户位置,当我尝试重定向到另一个域时,它给了我“重定向太多”错误,我想不出解决这个问题的方法.
目前我的代码如下所示
string CountryName = "";
var Country = HttpContext.Current.Response.Cookies["Country"];
Country.Expires = DateTime.Now.AddDays(365);
var ip = HttpContext.Current.Request.UserHostAddress;
if (!string.IsNullOrEmpty(ip) && ip != null && ip != "127.0.0.1")
using (var client = new WebServiceClient(xxxxx, "xxxxxxxx"))
var IpCountry = client.Country(ip);
CountryName = IpCountry.Country.Name;
switch (CountryName)
case "Denmark":
if (Country.Value != CountryName)
Country.Value = CountryName;
HttpContext.Current.Response.Redirect("/");
break;
case "United Kingdom":
if (Country.Value != CountryName)
Country.Value = CountryName;
HttpContext.Current.Response.Redirect("/en");
break;
case "Germany":
if (Country.Value != CountryName)
Country.Value = CountryName;
HttpContext.Current.Response.Redirect("/de");
break;
case "Sweden":
if (Country.Value != CountryName)
Country.Value = CountryName;
HttpContext.Current.Response.Redirect("/se");
break;
case "Norway":
if (Country.Value != CountryName)
Country.Value = CountryName;
HttpContext.Current.Response.Redirect("/no");
break;
default:
if (Country.Value != CountryName)
Country.Value = CountryName;
//HttpContext.Current.Response.Redirect("http://www.google.com");
break;
else if (loadedArgs.pageview.Area.ID != 2)
HttpContext.Current.Response.Redirect("/choose-country");
此外,我还想知道以更好的方式处理这种情况的其他可能方法,因此一旦设置了 cookie,此代码就不会在每次页面加载时运行。非常感谢。
【问题讨论】:
您的意思是,当您取消注释重定向到谷歌时,您会收到许多重定向错误? @VolodymyrBilyachat 不,当我注释掉所有重定向时它工作正常,否则它会给我错误重定向太多。这虽然有意义,因为此代码在页面加载时运行,并且在重定向后再次运行代码并进入无限循环。所以我想弄清楚如何预防? 你实际上在哪里设置带有国家名称的cookie? @Evk cookie 设置在 Country 变量中,并且在获取 CountryName 后,我正在存储类似 Country.Value = CountryName; 的值 使用自定义 http 处理程序为您处理此问题可能是更清洁的解决方案。 【参考方案1】:我无权访问您的代码,但是,如果我正确阅读了您的代码,重定向问题的解决方法是在任何创建/重定向逻辑之前检查 cookie 是否存在。我做了一些更改,请尝试一下,如果有任何问题,请告诉我。
var context = HttpContext.Current;
var cookieName = "Country";
var ip = context.Request.UserHostAddress;
if (!string.IsNullOrWhiteSpace(ip) && ip != "127.0.0.1")
//If the cookie is present (means cookie is set already) then return
if (context.Request.Cookies[cookieName] != null)
return;
string countryName;
using (var client = new WebServiceClient(xxxxx, "xxxxxxxx"))
var ipCountry = client.Country(ip);
countryName = ipCountry.Country.Name;
context.Response.Cookies.Add(new HttpCookie(cookieName)
Value = countryName,
Expires = DateTime.Now.AddDays(365)
);
switch (countryName)
case "Denmark":
context.Response.Redirect("/");
break;
case "United Kingdom":
context.Response.Redirect("/en");
break;
case "Germany":
context.Response.Redirect("/de");
break;
case "Sweden":
context.Response.Redirect("/se");
break;
case "Norway":
context.Response.Redirect("/no");
break;
default:
//context.Response.Redirect("http://www.google.com");
break;
else if (loadedArgs.pageview.Area.ID != 2)
context.Response.Redirect("/choose-country");
谢谢你, 索玛。
【讨论】:
【参考方案2】:您可以使用以下代码获取客户端 IP 地址。即,在您的网站中请求页面的机器的 IP 地址。
String UserIP = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (string.IsNullOrEmpty(UserIP))
UserIP = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
以下是我们需要用于 API URL 的格式。
freegeoip.net/format/IP_or_hostname
format –> 是响应输出格式。它可以是 CSV、XML 或 JSON。
例如,如果我们想获取 JSON 格式的响应,那么我们可以使用 API URL 作为“http://freegeoip.net/json/clientIPAddress_here”
string url = "http://freegeoip.net/json/" + UserIP.ToString();
WebClient client = new WebClient();
string jsonstring = client.DownloadString(url);
要获取示例响应格式,请直接在浏览器中运行此http://freegeoip.net/json/XX.XX.XX.XX(将 XX.XX.XX.XX 替换为所需的 IP 地址)URL。您将看到以下响应格式。
"ip":"xxx.xxx.xxx.xxx",
"country_code":"",
"country_name":"",
"region_code":"",
"region_name":"",
"city":"",
"zip_code":"",
"time_zone":"",
"latitude":0,
"longitude":0,
"metro_code":0
使用以下代码将响应转换为 JSON 对象,然后读取 JSON 对象的值并保存到会话变量或其他变量中。
dynamic dynObj = JsonConvert.DeserializeObject(jsonstring);
System.Web.HttpContext.Current.Session["LocId"] = dynObj.country_code;
您也可以使用Location 标头检测国家/地区
在 HttpWebRequest
上,您可以将 AllowAutoRedirect
设置为 false 以自行处理重定向。
// don't allow redirects, they are allowed by default so we're going to override
myRequest.AllowAutoRedirect = false;
// send the request
HttpWebResponse response = myRequest.GetResponse();
// check the header for a Location value
if( response.Headers["Location"] == null )
// null means no redirect
else
// anything non null means we got a redirect
解决“重定向过多”问题: 重定向循环就像 > "A 指向 B,B 指向 A" .这样的重定向将使浏览器处于无限循环中,并且永远不会显示网页。在过去,这种重定向或无限循环会导致浏览器挂起。谢天谢地,现代浏览器能够检测到这种重定向循环,并通过显示错误消息来打破循环:“错误 310 (net::ERR_TOO_MANY_REDIRECTS): there重定向太多”。
这个问题可能是在客户端或服务器端引起的。如果服务器端没有重定向循环,问题很可能只需要从浏览器中删除cookies就可以解决。
所以我建议请检查你的 routeconfig.cs 是否有这样的路由或类似的重定向操作,在从浏览器中删除 cookie 后指向自身
希望这会有所帮助:)
【讨论】:
您好,感谢您的回答,但这并不能解决我的问题。我的问题是“重定向太多”错误,因为我在页面加载观察器上有这个代码,它在每次调用页面时运行,所以重定向后代码再次运行并进入无限循环,所以我的基本问题是如何防止它进入无限循环? @UmarKhan 我已经更新了我的答案,请检查解决方案【参考方案3】:我认为问题在于无法识别请求是在重定向之前还是之后的逻辑。顺序好像是
The code executes once when a URL xyz.com
The redirect to xyz.com/en happens
Again the code executes and tries to redirect to xyz.com/en/en
这可以通过更多调试来确认。
如果请求的 URL 不以“en”或“de”结尾(该列表可以在应用程序中维护),我建议您的代码应该执行并重定向
您可能还需要更改处理默认国家/地区的方式,因为如果逻辑没有国家指示默认国家/地区,那么我上面提到的将不起作用。
【讨论】:
【参考方案4】:在 Asp.Net MVC 中,我有一个类可以处理无效 IP 地址并根据 IP 地址重定向它们。我使用以下代码:
protected override async void HandleUnauthorizedRequest(AuthorizationContext context)
var ipAddress = HttpContext.Current.Request.UserHostAddress;
if (await IpAddressValid(ipAddress)) return;
var urlHelper = new UrlHelper(context.RequestContext);
var address = urlHelper.Action("InvalidIpRange", "Account");
context.Result = new RedirectResult(address ?? "www.google.com");
private async Task<bool> IpAddressValid(string ipAddress)
if (ipAddress == "::1")
return true;
var longIp = Ip2Int(ipAddress);
var addr = await GeoIPCountry.ReturnGeoIpCountries(longIp, longIp); //dbContext.GeoIPCountries.Where(x => x.Start >= longIp && x.End <= longIp);
return addr.All(g => g.CountryCode == "US");
/// <summary>
/// Converts IP Address to Long Stack Space.
/// </summary>
/// <param name="ipAddress"></param>
/// <returns></returns>
public int Ip2Int(string ipAddress)
try
var addr = IPAddress.Parse(ipAddress);
uint ip =
(uint) IPAddress.NetworkToHostOrder((int) BitConverter.ToUInt32(addr.GetAddressBytes(), 0));
return (int)ip;
catch (Exception)
return 0;
在需要它的每个控制器的顶部,您所要做的就是添加 [IpAddressAuthorize] 标志,它会处理所有事情。这发生在任何其他操作之前,所以如果你应该能够很容易地修改它。
【讨论】:
【参考方案5】:您没有提供关于“在每个请求上运行的观察者”的太多信息,但如果它确实在每个请求上运行,它只会在您检查用户的国家/地区后重定向用户时再次运行。
要对此进行调试,只需在调用重定向的任何位置放置断点,然后检查哪个被重复调用。
例如,假设用户来自丹麦,在这种情况下您
context.Response.Redirect("/");
但这会导致您的“观察者”再次运行并再次重定向!所以你需要通过放置另一个cookie来检查重定向是否已经发生,或者通过检查请求的页面是否已经是特定语言的页面,因此不需要再次重定向。
【讨论】:
以上是关于根据IP将用户重定向到子域的主要内容,如果未能解决你的问题,请参考以下文章