2016-04-29 4 views
7

Я пытаюсь перенаправить пользователя в поддомену, основываясь на его местоположении IP-адреса. У меня есть наблюдатель нагрузки страницы, который запускает функцию для каждого запроса и получает местоположение пользователя, и когда я пытаюсь перенаправить на другой домен, он дает мне ошибку «Слишком много переадресаций», и я не могу найти способ решить эту проблему ,Перенаправление пользователя в поддомену на основе 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. Спасибо заранее.

+0

Вы имеете в виду, когда вы раскомментируете перенаправление на google, вы получаете ошибку во многих переадресациях? –

+0

@VolodymyrBilyachat Нет, когда я прокомментирую все переадресации, он работает отлично, другой мудрый он дает мне ошибку Слишком много перенаправлений. что имеет смысл, так как этот код работает при загрузке страницы, и после перенаправления он снова запускает код и попадает в бесконечный цикл. Поэтому я хочу выяснить, как предотвратить это? –

+0

Где вы на самом деле устанавливаете cookie с названием страны? – Evk

ответ

0

Вы можете использовать приведенный ниже код, чтобы получить IP-адрес клиента. то есть IP-адрес машины, который запрашивал страницу на вашем веб-сайте.

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

Ниже приведен формат, который необходимо использовать для URL-адреса API.

freegeoip.net/{format}/{IP_or_hostname} 

формат -> формат выходного сигнала ответа. Это может быть CSV или XML или JSON.

Например, если мы хотели бы получить ответ в формате JSON, то мы могли бы использовать URL 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 ложь, чтобы обрабатывать перенаправлять себя.

// 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 
} 

Решение «Слишком много переадресаций» вопрос: цикл Перенаправление подобна ситуации, в которой>«А точки В и В точках обратно в» . Такое перенаправление будет поддерживать браузер в бесконечном цикле, и веб-страница никогда не будет отображаться. В старые времена такие переадресации или бесконечные контуры, используемые для создания зависающего браузера. В настоящее время современные браузеры способны обнаруживать такие петли переадресации, и они прерывают цикл, вызывая сообщение об ошибке: «Ошибка 310 (net :: ERR_TOO_MANY_REDIRECTS): там было слишком много перенаправлений ».

Эта проблема может быть вызвана либо на стороне клиента, либо на сервере. Если на стороне сервера нет цикла перенаправления, проблема, скорее всего, будет решена только путем удаления файлов cookie из браузера.

Так что я предлагаю проверить ваш маршрут.CS для такого маршрута или аналогичной операции перенаправления, который указует на сам себя после удаления куки из браузера

Надеется, что это помогает :)

+0

Привет, спасибо за ваш ответ, но это не решает мою проблему. Моя проблема связана с ошибкой «Слишком много переадресаций», поскольку у меня есть этот код на наблюдателе нагрузки страницы, который запускается при каждом вызове страницы, поэтому после перенаправления код запускается снова, и он попадает в бесконечный цикл, поэтому мой основной вопрос заключается в том, как его предотвратить попадая в бесконечную петлю? –

+0

@UmarKhan Я обновил свой ответ, пожалуйста, проверьте решение – Aminul

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 запрашивается не заканчивается с «собственной» или «де» (список может быть сохранен в приложении)

Вам может понадобиться изменить путь вы также обрабатываете свою страну по умолчанию, потому что, если логика не является страной, указывающей страну по умолчанию, то то, о чем я говорил выше, не будет работать.

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] флаг и он будет обрабатывать все. Это происходит перед любым другим действием, поэтому, если вы сможете легко его модифицировать.

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"); 
} 

Спасибо, Сома.

0

Вы не предоставляете много информации об «наблюдателе, который работает по каждому запросу», но если он действительно выполняется при каждом запросе, он будет снова запущен при перенаправлении пользователя после проверки их страны.

Чтобы отладить это, просто поместите точки останова везде, где вы вызываете перенаправление, и проверьте, какой из них неоднократно вызывается.

Например, допустим, что пользователь из Дании, в этом случае вы

context.Response.Redirect("/"); 

Но это приведет к тому, «наблюдатель», чтобы запустить снова и снова переадресовать! Поэтому вам нужно проверить, не произошло ли перенаправление, помещая еще один файл cookie или проверяя, является ли запрошенная страница уже языковой страницей, и поэтому нет необходимости перенаправлять ее снова.