How to get client domain name from a request - c#

I have wcf-service host at kkk.com. When someone(other domain) request to my service I use this code to get client's domain name.
public static string GetClientDomian(HttpContext context)
{
string clientDomain = string.Empty;
clientDomain = context.Request.Url.Host;
return clientDomain;
}
But it's always return kkk.com not return the client's domain name. How to solve this? Thanks.

OK. This code is work. Change context.Request.Url.Host to context.Request.UrlReferrer.Host
Like this
public static string GetClientDomian(HttpContext context)
{
string clientDomain = string.Empty;
clientDomain = context.Request.UrlReferrer.Host;
return clientDomain;
}

Related

Is it possible to call WebApi inside Middleware Asp .Net Core

I'm workin on a MVC Aps.Net Core project and I have this situation :
User A is loggedin device A, and user B is trying to login in device A. I allow to login the user B to device A without problem, but in that case I show pop-up message to user A that user A now is disconected from device A.
Evrithing works fine. I call WebApi where I have SQL function, and that function do all the job. The problem is that I have the same code(that call the WebApi) in each function on my project. So I was thinking to make custom middleware so in that way I don't need to replace that code in every function/method in my project.
This is what I tried :
public class Middleware
{
private readonly RequestDelegate _next;
string strBaseUrl = string.Empty;
string strMappaturaUrl = string.Empty;
private readonly IConfiguration config;
private readonly HttpClient client;
public Middleware(RequestDelegate next, IConfiguration _config, HttpClient _client)
{
_next = next;
client = _client;
config = _config;
strBaseUrl = config.GetValue<string>("AppSettings:BaseUrl");
strMappaturaUrl = config.GetValue<string>("AppSettings:MapUrl");
}
public async Task Invoke(HttpContext httpContext)
{
string returnErrore = string.Empty;
CheckUtenteDTO userRequest = new CheckUtenteDTO();
string strUrlApi = string.Empty;
string strContext = string.Empty;
try
{
userRequest.user = HttpContext.Session.GetString("nomeUten");
userRequest.macchina = HttpContext.Session.GetString("macchina");
//Here I call WebApi where I have SQL functio
strUrlApi = config.GetValue<string>("AppSettings:BaseUrl") + "/Users/CheckLoginUser";
string stringData = JsonConvert.SerializeObject(userRequest);
var contentData = new StringContent(stringData, System.Text.Encoding.UTF8, "application/json");
using (var responseMessage = await client.PostAsync(strUrlApi, contentData))
{
if (responseMessage.IsSuccessStatusCode)
{
strContext = await responseMessage.Content.ReadAsStringAsync();
var strReturn = JsonConvert.DeserializeObject<string>(strContext);
if (string.IsNullOrWhiteSpace(strReturn))
returnErrore = string.Empty;
else
throw new UtenteException(strReturn);
}
else
{
strContext = await responseMessage.Content.ReadAsStringAsync();
throw new Exception(strContext);
}
}
}
catch (UserException ex1)
{
returnErrore = ex1.Message.Trim();
HttpContext.Session.SetString("strErrore", ex1.Message);
HttpContext.Session.SetString("nextAction", "LogoutAfterCheck");
HttpContext.Session.SetString("nextController", "Login");
}
catch (Exception ex)
{
returnErrore = ex.Message.Trim();
HttpContext.Session.SetString("strErrore", ex.Message);
HttpContext.Session.SetString("nextAction", "Index");
HttpContext.Session.SetString("nextController", "HomeScreen");
}
return Json(returnErrore);
//return _next(httpContext);
}
}
// Extension method used to add the middleware to the HTTP request pipeline.
public static class MiddlewareExtensions
{
public static IApplicationBuilder UseMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<Middleware>();
}
}
}
And I get this errors .
Is it possible to do it in this way?
Any suggestions how to fix this?
Thanks in advance!
That looks like your middleware don't have access to HttpContext and thus the error. In such case, you can pass the context as a parameter to your middleware from your presentation layer where you have access to HttpContext and calling the Middleware function.
Essentially, you are using only the below two parameters from session .. then why not just extract them in your presentation layer and pass them as argument to the middleware function
userRequest.user = HttpContext.Session.GetString("nomeUten");
userRequest.macchina = HttpContext.Session.GetString("macchina");
Change your Invoke method signature to
Task Invoke(string user, string macchina) //assuming both are type string

I want to use an out parameter with string variable

I want to use an out parameter with string variable.
For Example:
string Url = "https://learn.microsoft.com/tr-tr/dotnet/csharp/language-reference/keywords/out-parameter-modifier"
string BaseUrl = this.DecompositionUrl(out Url).BaseUrl;
string ServiceUrl = this.DecompositioUrl(out Url).ServiceUrl;
I want to using a method like this.
public static string DecompositionUrl(out string Urlr)
{
// enter here :
BaseUrl = Urlr.Substring(0,40);
ServiceUrl = Urlr.Substring(40,Urlr.Length);
}
When returned my DecompositionUrl I want to set BaseUrl and ServiceUrl
You need to declare out parameters for the two values that you intend to return from your method: baseUrl and serviceUrl. The source url needs to be passed in through an ordinary parameter (not out).
public static void DecompositionUrl(string url, out string baseUrl, out string serviceUrl)
{
baseUrl = url.Substring(0, 40);
serviceUrl = url.Substring(40);
}
You would then call your method like so:
string url = "https://learn.microsoft.com/tr-tr/dotnet/csharp/language-reference/keywords/out-parameter-modifier"
DecompositionUrl(url, out var baseUrl, our var serviceUrl);
Console.WriteLine($"Base URL is {baseUrl} and service URL is {serviceUrl}.");
C# 7 allows you to return a 'tuple' as the result of a method like this
public static (string, string) DecompositionUrl(string url)
{
var baseUrl = ...;
var serviceUrl = ...;
return (baseUrl, serviceUrl);
}
You can then use it like this
(string baseUrl, string serviceUrl) = DecompositionUrl("https://learn.microsoft.com/tr-tr/dotnet/csharp/language-reference/keywords/out-parameter-modifier");
I think that's better than using the out keyword since it's clearer what's input and what's output.

How to get authenticated user's name, IP address, and the controller action being called from an HTTP Filter?

I'm trying to audit my action events on the controller. I want to keep track of authenticated user's name, his IP address, and controller action being called.
My filter code:
public class AuditAttribute : System.Web.Http.Filters.ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext filterContext)
{
var request = filterContext.Request;
// get user name + ip address + controlleraction
base.OnActionExecuting(filterContext);
}
I was searching on the internet only to see examples of how to do it for Mvc but not for HTTP. For instance, this link here talks about how to audit events for Mvc: http://rion.io/2013/03/03/implementing-audit-trails-using-asp-net-mvc-actionfilters/
This link however talks about how to capture IP address for HTTP web app: Capture request IP Address in Web API Authentication Filter
But I'm struggling to follow it. Not sure where exactly to put this code in.
Appreciate your help.
Try using below code.
UPDATE:
For asp.net web api, please try this
public class AuditAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
var context = actionContext.RequestContext;
var user = context.Principal.Identity.IsAuthenticated ? context.Principal.Identity.Name : string.Empty;
var ip = GetClientIpAddress(actionContext.Request);
var action = actionContext.ActionDescriptor.ActionName;
var controller = actionContext.ActionDescriptor.ControllerDescriptor.ControllerName;
base.OnActionExecuting(actionContext);
}
private string GetClientIpAddress(HttpRequestMessage request)
{
if (request.Properties.ContainsKey("MS_HttpContext"))
{
return IPAddress.Parse(((HttpContextBase)request.Properties["MS_HttpContext"]).Request.UserHostAddress).ToString();
}
if (request.Properties.ContainsKey("MS_OwinContext"))
{
return IPAddress.Parse(((OwinContext)request.Properties["MS_OwinContext"]).Request.RemoteIpAddress).ToString();
}
return String.Empty;
}
}
And for asp.net MVC, you can try this
public class AuditAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// get user name + ip address + controlleraction
var controller = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
var action = filterContext.ActionDescriptor.ActionName;
var ip = filterContext.HttpContext.Request.UserHostAddress;
var dateTime = filterContext.HttpContext.Timestamp;
var user = GetUserName(filterContext.HttpContext);
}
private string GetUserName(HttpContext httpContext)
{
var userName = string.Empty;
var context = httpContext.Current;
if (context != null && context.User != null && context.User.Identity.IsAuthenticated)
{
userName = context.User.Identity.Name;
}
else
{
var threadPincipal = Thread.CurrentPrincipal;
if (threadPincipal != null && threadPincipal.Identity.IsAuthenticated)
{
userName = threadPincipal.Identity.Name;
}
}
return userName;
}
}
Update 2 : Retrieving Client IP address is always a tricky business because there are lot of factors that has to be considered. How are clients accessing the application? Are they coming thru a proxy server? IP addresses can be spoofed, so there is no 100% reliable way. Looking at the Http Headers will provide you some level of success in both web api and mvc. But you always have to consider the fact that there will be cases where client IP is not valid.
How can I get the client's IP address in ASP.NET MVC?
try this
using System.Web;
and use this
HttpContext.Current.Request.UserHostAddress

Asp Net Web API 2.1 get client IP address

Hello I need get client IP that request some method in web api,
I have tried to use this code from here but it always returns server local IP,
how to get in correct way ?
HttpContext.Current.Request.UserHostAddress;
from other questions:
public static class HttpRequestMessageExtensions
{
private const string HttpContext = "MS_HttpContext";
private const string RemoteEndpointMessage = "System.ServiceModel.Channels.RemoteEndpointMessageProperty";
public static string GetClientIpAddress(this HttpRequestMessage request)
{
if (request.Properties.ContainsKey(HttpContext))
{
dynamic ctx = request.Properties[HttpContext];
if (ctx != null)
{
return ctx.Request.UserHostAddress;
}
}
if (request.Properties.ContainsKey(RemoteEndpointMessage))
{
dynamic remoteEndpoint = request.Properties[RemoteEndpointMessage];
if (remoteEndpoint != null)
{
return remoteEndpoint.Address;
}
}
return null;
}
}
Following link might help you. Here's code from the following link.
reference : getting-the-client-ip-via-asp-net-web-api
using System.Net.Http;
using System.ServiceModel.Channels;
using System.Web;
using System.Web.Http;
namespace Trikks.Controllers.Api
{
public class IpController : ApiController
{
public string GetIp()
{
return GetClientIp();
}
private string GetClientIp(HttpRequestMessage request = null)
{
request = request ?? Request;
if (request.Properties.ContainsKey("MS_HttpContext"))
{
return ((HttpContextWrapper)request.Properties["MS_HttpContext"]).Request.UserHostAddress;
}
else if (request.Properties.ContainsKey(RemoteEndpointMessageProperty.Name))
{
RemoteEndpointMessageProperty prop = (RemoteEndpointMessageProperty)request.Properties[RemoteEndpointMessageProperty.Name];
return prop.Address;
}
else if (HttpContext.Current != null)
{
return HttpContext.Current.Request.UserHostAddress;
}
else
{
return null;
}
}
}
}
Another way of doing this is below.
reference: how-to-access-the-client-s-ip-address
For web hosted version
string clientAddress = HttpContext.Current.Request.UserHostAddress;
For self hosted
object property;
Request.Properties.TryGetValue(typeof(RemoteEndpointMessageProperty).FullName, out property);
RemoteEndpointMessageProperty remoteProperty = property as RemoteEndpointMessageProperty;
With Web API 2.2: Request.GetOwinContext().Request.RemoteIpAddress
Try to get the Ip using
ip = HttpContext.Current != null ? HttpContext.Current.Request.UserHostAddress : "";
I think this is the most clear solution, using an extension method:
public static class HttpRequestMessageExtensions
{
private const string HttpContext = "MS_HttpContext";
private const string RemoteEndpointMessage = "System.ServiceModel.Channels.RemoteEndpointMessageProperty";
public static string GetClientIpAddress(this HttpRequestMessage request)
{
if (request.Properties.ContainsKey(HttpContext))
{
dynamic ctx = request.Properties[HttpContext];
if (ctx != null)
{
return ctx.Request.UserHostAddress;
}
}
if (request.Properties.ContainsKey(RemoteEndpointMessage))
{
dynamic remoteEndpoint = request.Properties[RemoteEndpointMessage];
if (remoteEndpoint != null)
{
return remoteEndpoint.Address;
}
}
return null;
}
}
So just use it like:
var ipAddress = request.GetClientIpAddress();
We use this in our projects.
Source/Reference: Retrieving the client’s IP address in ASP.NET Web API
If you're self-hosting with Asp.Net 2.1 using the OWIN Self-host NuGet package you can use the following code:
private string getClientIp(HttpRequestMessage request = null)
{
if (request == null)
{
return null;
}
if (request.Properties.ContainsKey("MS_OwinContext"))
{
return ((OwinContext) request.Properties["MS_OwinContext"]).Request.RemoteIpAddress;
}
return null;
}
Replying to this 4 year old post, because this seems overcomplicated to me, at least if you're hosting on IIS.
Here's how I solved it:
using System;
using System.Net;
using System.Web;
using System.Web.Http;
...
[HttpPost]
[Route("ContactForm")]
public IHttpActionResult PostContactForm([FromBody] ContactForm contactForm)
{
var hostname = HttpContext.Current.Request.UserHostAddress;
IPAddress ipAddress = IPAddress.Parse(hostname);
IPHostEntry ipHostEntry = Dns.GetHostEntry(ipAddress);
...
Unlike OP, this gives me the client IP and client hostname, not the server. Perhaps they've fixed the bug since then?
It's better to cast it to HttpContextBase, this way you can mock and test it more easily
public string GetUserIp(HttpRequestMessage request)
{
if (request.Properties.ContainsKey("MS_HttpContext"))
{
var ctx = request.Properties["MS_HttpContext"] as HttpContextBase;
if (ctx != null)
{
return ctx.Request.UserHostAddress;
}
}
return null;
}
My solution is similar to user1587439's answer, but works directly on the controller's instance (instead of accessing HttpContext.Current).
In the 'Watch' window, I saw that this.RequestContext.WebRequest contains the 'UserHostAddress' property, but since it relies on the WebHostHttpRequestContext type (which is internal to the 'System.Web.Http' assembly) - I wasn't able to access it directly, so I used reflection to directly access it:
string hostAddress = ((System.Web.HttpRequestWrapper)this.RequestContext.GetType().Assembly.GetType("System.Web.Http.WebHost.WebHostHttpRequestContext").GetProperty("WebRequest").GetMethod.Invoke(this.RequestContext, null)).UserHostAddress;
I'm not saying it's the best solution. using reflection may cause issues in the future in case of framework upgrade (due to name changes), but for my needs it's perfect
string userRequest = System.Web.HttpContext.Current.Request.UserHostAddress;
This works on me.
System.Web.HttpContext.Current.Request.UserHostName; this one return me the same return I get from the UserHostAddress.

How can I authenticate against Active Directory in Nancy?

It's an outdated article, but http://msdn.microsoft.com/en-us/library/ff650308.aspx#paght000026_step3 illustrates what I want to do. I've chosen Nancy as my web framework because of it's simplicity and low-ceremony approach. So, I need a way to authenticate against Active Directory using Nancy.
In ASP.NET, it looks like you can just switch between a db-based membership provider and Active Directory just by some settings in your web.config file. I don't need that specifically, but the ability to switch between dev and production would be amazing.
How can this be done?
Really the solution is much simpler than it may seem. Just think of Active Directory as a repository for your users (just like a database). All you need to do is query AD to verify that the username and password entered are valid. SO, just use Nancy's Forms Validation and handle the connetion to AD in your implementation of IUserMapper. Here's what I came up with for my user mapper:
public class ActiveDirectoryUserMapper : IUserMapper, IUserLoginManager
{
static readonly Dictionary<Guid, long> LoggedInUserIds = new Dictionary<Guid, long>();
readonly IAdminUserValidator _adminUserValidator;
readonly IAdminUserFetcher _adminUserFetcher;
readonly ISessionContainer _sessionContainer;
public ActiveDirectoryUserMapper(IAdminUserValidator adminUserValidator, IAdminUserFetcher adminUserFetcher, ISessionContainer sessionContainer)
{
_adminUserValidator = adminUserValidator;
_adminUserFetcher = adminUserFetcher;
_sessionContainer = sessionContainer;
}
public IUserIdentity GetUserFromIdentifier(Guid identifier, NancyContext context)
{
_sessionContainer.OpenSession();
var adminUserId = LoggedInUserIds.First(x => x.Key == identifier).Value;
var adminUser = _adminUserFetcher.GetAdminUser(adminUserId);
return new ApiUserIdentity(adminUser);
}
public Guid Login(string username, string clearTextPassword, string domain)
{
var adminUser = _adminUserValidator.ValidateAndReturnAdminUser(username, clearTextPassword, domain);
var identifier = Guid.NewGuid();
LoggedInUserIds.Add(identifier, adminUser.Id);
return identifier;
}
}
I'm keeping a record in my database to handle roles, so this class handles verifying with AD and fetching the user from the database:
public class AdminUserValidator : IAdminUserValidator
{
readonly IActiveDirectoryUserValidator _activeDirectoryUserValidator;
readonly IAdminUserFetcher _adminUserFetcher;
public AdminUserValidator(IAdminUserFetcher adminUserFetcher,
IActiveDirectoryUserValidator activeDirectoryUserValidator)
{
_adminUserFetcher = adminUserFetcher;
_activeDirectoryUserValidator = activeDirectoryUserValidator;
}
#region IAdminUserValidator Members
public AdminUser ValidateAndReturnAdminUser(string username, string clearTextPassword, string domain)
{
_activeDirectoryUserValidator.Validate(username, clearTextPassword, domain);
return _adminUserFetcher.GetAdminUser(1);
}
#endregion
}
And this class actually verifies that the username/password combination exist in Active Directory:
public class ActiveDirectoryUserValidator : IActiveDirectoryUserValidator
{
public void Validate(string username, string clearTextPassword, string domain)
{
using (var principalContext = new PrincipalContext(ContextType.Domain, domain))
{
// validate the credentials
bool isValid = principalContext.ValidateCredentials(username, clearTextPassword);
if (!isValid)
throw new Exception("Invalid username or password.");
}
}
}

Categories