根据IP

时间:2016-04-29 08:28:13

标签: c# .net redirect http-redirect response.redirect

我正在尝试根据用户的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,此代码就不会在每个页面加载上运行。非常感谢提前。

5 个答案:

答案 0 :(得分: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");
}

谢谢你, 索马。

答案 1 :(得分:0)

您可以使用以下代码获取客户端IP地址。即,在您的网站上请求页面的机器的IP地址。

String UserIP = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (string.IsNullOrEmpty(UserIP))
{
    UserIP = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
}

以下是我们需要用于API网址的格式。

freegeoip.net/{format}/{IP_or_hostname}

格式 - >是响应输出格式。它可以是CSV或XML或JSON。

例如,如果我们想以JSON格式获取响应,那么我们可以将API网址用作“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
}

解决“太多重定向”问题: 重定向循环就像一种情况,其中> “B点和B点指向A” 。这样的重定向将使浏览器保持无限循环,并且永远不会显示网页。在过去,这种重定向或无限循环用于导致浏览器挂起。谢谢,现代浏览器能够检测到这样的重定向循环,并通过显示错误消息来打破循环:“错误310(net :: ERR_TOO_MANY_REDIRECTS):那里有太多的重定向“。

此问题可能是在客户端或服务器端引起的。如果服务器端没有重定向循环,则只需从浏览器中删除cookie即可解决问题。

所以我建议请检查您的routeconfig.cs以获取此类路由或类似的重定向操作,在从浏览器中删除Cookie后指向自身

希望这有帮助:)

答案 2 :(得分:0)

我认为问题在于无法识别请求是在重定向之前还是之后的逻辑。序列似乎是

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”结尾(列表可以在应用程序中维护),我建议您的代码应该执行并重定向

您可能还需要更改处理默认国家/地区的方式,因为如果逻辑没有国家/地区表示默认国家/地区,那么我上面提到的内容将无效。

答案 3 :(得分:0)

在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]标志,它将处理所有事情。这发生在任何其他操作之前,所以如果您应该能够很容易地修改它。

答案 4 :(得分:0)

您没有提供有关“在每个请求上运行的观察者”的大量信息,但如果它确实在每个请求上运行,则只有在您检查其国家/地区后重定向用户时,它才会再次运行。

要对此进行调试,只需将断点放在您调用重定向的任何位置,并检查哪一个被重复调用。

例如,假设用户来自丹麦,在这种情况下,您

context.Response.Redirect("/");

但是这会导致你的'观察者'再次运行并再次重定向!因此,您需要通过放置另一个cookie来检查重定向是否已经发生,或者检查所请求的页面是否已经是特定于语言的页面,因此无需再次重定向。