Hope you all are fine.
I'm working on a project that based on vue-js (FRONTEND) and .net core web api (BACKEND).
The issue I'm facing is I've to get the client IP-ADDRESS using that C# dll which is located in Server. I don't know how to get it.
Please let me know if any of you know.
Will be highly appreciated.
The requester's IP address can be found on the Connection value of the HttpContext for the request, as RemoteIpAddress. For example, in an ASP.NET Core controller action:
public IActionResult MyAction()
{
IPAddress? ipAddress = Request.HttpContext.Connection.RemoteIpAddress;
return Ok();
}
As noted in docs, this might be null.
Related
I have an ASP.NET Core MVC web application that uses Identity to handle user account Authentication and Authorization. When running the app on my local IIS express everything was working properly. After deploying the app to a shared web server I started to notice that the logged-in user accounts would get logged out at seemingly random intervals. Through experimentation, I was able to determine that the log-outs were occurring whether the account was active or idle. They were occuring at no recuring time interval and completely unrelated to any expiry time that I set on my cookies. The logouts were occuring on every view in the web app so I couldn't pin the issue to any particular controller. Also I use the same Database for the published and the local testing version of the app and therefore the same user accounts. I anyone has an idea where to start looking for a solution it would be greatly appreciated.
I posted this question because there is a great answer that 90% solves the issue Here however of the multiple forums that I have been scouring over the last few days there are none with an accepted answer. I am posting this answer to address this. The underlying cause of the issue is that IIS application pool is being reset or recyling and on a shared host with multiple applications using it this can be happening fairly frequently. As is suggested in the above link Data Protection has to be used to persist the keys if IIS application pool recycles. Here is the code offered in the original answer.
services.AddDataProtection()
.PersistKeysToFileSystem(new System.IO.DirectoryInfo("SOME WHERE IN STORAGE"))
//.ProtectKeysWithCertificate(new X509Certificate2());
.SetDefaultKeyLifetime(TimeSpan.FromDays(90));
This code is to be added in ConfigureServices in Startup.cs
As my application is being hosted on a shared server using .PersistKeysToFileSystem was not an option so instead I persisted the keys using DbContext like this:
services.AddDataProtection().PersistKeysToDbContext<MyKeysContext>()
.SetDefaultKeyLifetime(TimeSpan.FromDays(90));
Based on This article here I build MyKeysContext as follows.
// Add a DbContext to store your Database Keys
services.AddDbContext<MyKeysContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("MyKeysConnection")));
In ConfigureServices in Startup.cs and then created a class called MyKeysContext as follows:
using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using WebApp1.Data;
namespace WebApp1
{
public class MyKeysContext : DbContext, IDataProtectionKeyContext
{
// A recommended constructor overload when using EF Core
// with dependency injection.
public MyKeysContext(DbContextOptions<MyKeysContext> options)
: base(options) { }
// This maps to the table that stores keys.
public DbSet<DataProtectionKey> DataProtectionKeys { get; set; }
}
}
I created the database on my Host this will probably be different so I have omitted this step. then I applied the migrations to the database like this.
Add-Migration AddDataProtectionKeys -Context MyKeysContext
Update-Database -Context MyKeysContext
I have an ASP.NET Core 5 web app (actually a blazor server app) and another ASP.NET Core 5 Web API, both running on IIS in a domain environment.
I have configured Windows auth so that users can authenticate with the Blazor server app, and this returns the expected domain user's identity from the HttpContext.
If I use the Web API through Swagger to get the users identity from the HttpContext, I also get the expected domain user's identity. However if naively call from the Blazor server app using the HttpClient (given by DI) to the Web API, I get the app pool identity for the user instead.
There are hundreds of posts on this subject and why this happens (i.e.)
https://github.com/dotnet/runtime/issues/17828
.Net Core WindowsIdentity impersonation does not seem to be working
However my question is essentially even if I do manage to get the stars to align and get all the infrastructure config correct is there any way to get the middleware to provide an HttpClient that is already "impersonated" or am I forced to wrap every use of HttpClient something like this:
https://stackoverflow.com/a/66511109/29411
IPrincipal p = _httpContextAccessor.HttpContext.User;
HttpResponseMessage result = null;
if (p.Identity is WindowsIdentity wid)
{
await WindowsIdentity.RunImpersonated(wid.AccessToken, async () =>
{
result = await _client.GetAsync("APIController/Action");
});
}
.Net 5 running Impersonated
(I am running this in Blazor Server)
I have only recently solved this so at present I think everything will need to be wrapped but I'll update if I find anything that solves that.
I have seen a lot of references to using an IHttpConextAccessor and lots of problems with this being null. This article from Microsoft suggests that this shouldn’t be used (Certainly in Blazor)
MS-Docs
Solution:
To get the user to impersonate use the AuthenticationStateProvider and get the user from this and cast to a WindowsIDentity to retrieve the AccessToken.
This works in both a service and a razor component.
Inject the AuthenticationStateProvider and then in your method use the following code:
var authState = await _authenticationStateProvider.GetAuthenticationStateAsync();
var user = authState.User;
var userToImpersonate = (WindowsIdentity)user.Identity;
await WindowsIdentity.RunImpersonatedAsync(userToImpersonate.AccessToken, async () =>
{
// Your Code in here
}
I'd like to know under what IIS' Application Name my asp.net core 3 application is running at start time. Possibly also Site Name.
There is a misleading IHostingEnvironment.ApplicationName which is something else (assembly name in fact).
Any idea?
As far as I know, there is no build-in method which could get the web application name. Here is a workaround. We could try to use System.Security.Principal.WindowsIdentity.GetCurrent() to get the current identity name.
Normally, the identity name is the IIS web site name if you don't modify it.
Details, you could refer to below codes:
public IActionResult Index()
{
string name = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
return View();
}
Result:
Notice:Remove the IIS application pool is the IIS web site name
I need to obtain the base URL of the ASP.NET Core application inside of one of the HostedServices.
I need this because it does a request to the same ASP.NET core application in which it is hosted (the purpose is warming up, to improve the first call performance to the User).
For now my solution is to keep the base URL in the config file or just in the hosted service private variable.
https://github.com/BBGONE/JRIApp.Core/blob/master/DEMOS/RIAppDemoMVC/RIAppDemo/Utils/WarmUpService.cs
But i think, there's a way to obtain it from the startup code, but i don't know where it is hidden.
Anybody know how it can be obtained?
P.S. - there are solutions to obtain it from the request information, but the HostedService is started before any request have been done. So it's not suitable in this case.
I have found how to obtain the address of the appllication.
public void Configure(IApplicationBuilder application)
{
var addresses = application.ServerFeatures.Get<IServerAddressesFeature>().Addresses;
}
Although it has an issue https://github.com/aspnet/Hosting/issues/811 and can not be used if the application is hosted in the IIS or IIS Express.
They say:
That's not going to work for IIS or IIS Express. IIS is running as a
reverse proxy. It picks a random port for your process to listen on
and does not flow the public address information to you. The only way
to get the public address information is from incoming requests.
The ASP.NET Core Module generates a dynamic port to assign to the backend process. CreateDefaultBuilder calls the UseIISIntegration method. UseIISIntegration configures Kestrel to listen on the dynamic port at the localhost IP address (127.0.0.1). If the dynamic port is 1234, Kestrel listens at 127.0.0.1:1234. This configuration replaces other URL configurations provided by.
But if you get the feature from the WebHost after it was built, then this can be used to get the local address for warm up.
I tried this way:
public static void Main(string[] args)
{
var builder = CreateWebHostBuilder(args);
var webHost = builder.Build();
var addresses = webHost.ServerFeatures.Get<IServerAddressesFeature>().Addresses;
var address = addresses.FirstOrDefault();
AppDomain.CurrentDomain.SetData("BaseUrl", address?? "");
webHost.Run();
}
and got the local Kestrel address in the WarmUpService like this:
string baseUrl = AppDomain.CurrentDomain.GetData("BaseUrl").ToString();
I have developed an application in asp.net core and used signalR. When i publish it in root directory it works fine, but if i publish it inside virtual directory it doesn't work. My signalR hub is always pointing to the root directory.
Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// ... other middleware ...
app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("/chat");
});
}
And i have initialized it in client side like this,
chat.js
var connection = new signalR.HubConnection("/chat");
After publishing it inside virtual directory(/development/chatapp/source) it points like this,
http://localhost:100/chat?userId=1
But actually it has to point like this, so that it will work
http://localhost:100/development/chatapp/source/chat?userId=1
I have used asp.net core 2.0 and this signalR version(1.0.0-preview1-final).
Someone please suggest me to resolve this issue.
With the help of my friend i have found the root cause for this issue and i fixed it. Actually javascript doesn't know whether the application is hosted in root folder or sub folder(in virtual directory). It always points the root folder.
So when we are initializing it in js like this(new signalR.HubConnection("/chat")), it points the root directory as below,
http://localhost:100/chat?userId=1
Since javascript doesn't aware of IIS hosting, we need to tell the relative path from c#. So i get my application's base path as follows in controller,
ViewData["PathBase"] = Request.PathBase.ToString();
And if it has some value i just prepend it to '/chat', otherwise i just initialize it as '/chat'.
var connection = new signalR.HubConnection("/development/chatapp/source/chat");
This solves my problem :-)
Kailash P : With the help of my friend i have found the root ...
OK, thanks for your sharing.
I'm publish the SignalR Chat sample to IIS but NOT WORKS --X
SignalRChat :
Tutorial: Get started with ASP.NET Core SignalR
https://learn.microsoft.com/zh-tw/aspnet/core/tutorials/signalr?view=aspnetcore-2.2&tabs=visual-studio
*With Visual Studio debugging, the sample are works but NOT WORKS publish to IIS.
In page load, the send message button not enabled because there have some errors :
Failed to load resource: the server responded with a status of 500 (Internal Server Error) chatHub/negotiate:1
[2019-11-18T06:40:26.977Z] Error: Failed to complete negotiation with the server: Error: Internal Server Error Utils.ts:179
--
After add the vitural directory the SignalR Chat sample WORKS :
var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();
->
var connection = new signalR.HubConnectionBuilder().withUrl("/chat1/chatHub").build();
Don't know why there have no any official note about this problem (SignalR publishing).
[NET Core 2.2]
[Visual Studio 2019]