I have two Web API methods called in different cases. I have used the SetString method and the value is set in method 1 but when the 2nd method is called for other cases, accessing the value using the GetString method it returns the value as null.
public string Method1(string args)
{
HttpContext.Session.SetString("key", "value"); // value is set in this method.
}
public string Method2(string args)
{
string value = HttpContext.Session.GetString("key"); // value is obtained as null here
}
Any suggestions to resolve this issue. I have added controller manually in the blazor server-side application for WebAPI call.
options.Cookie.SameSite = SameSiteMode.None must be used to allow cross-site cookie use.
https://learn.microsoft.com/en-us/aspnet/core/security/samesite?view=aspnetcore-5.0
Startup#ConfigureServices
services.AddSession(options => {
options.Cookie.SameSite = SameSiteMode.None;
options.IdleTimeout = TimeSpan.FromSeconds(600); // 10 minutes
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
Startup#Configure
app.UseSession();
The order of middleware is important. Call UseSession after UseRouting and before UseEndpoints. See Middleware Ordering.
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/app-state?view=aspnetcore-5.0
If you run your app on multiple instances, you'll need to choose a strategy. Storing sessions using Distributed Cache is preferable. More info: https://dzone.com/articles/aspnet-core-session-storage-strategies
Another way of solving multiple server issue, is to use sticky sessions on your load balancer. This is not recommended because of the risc of uneven spread of load.
If you are able to get rid of the need for sessions in your app, I would highly recommend that.
Related
I am using Masstransit to send Request/Response via servicebus between two services(dont ask why).
I would like to set-up custom application insights telemetry. I know that ServiceBus Messages add Diagnostic metadata so consumer can extract it and use it to add correlation between services. However I can't access it in MassTransit, or at least I dont know how.
Any tips?
Couple of months passed and solution i implemented proves to be a good one.
I created class that implements IReceiveObserver. On PreReceive I am able to access (ServiceBusReceiveContext)context and start Telemetry operation that has correct parent id. so it looks like this:
public Task PreReceive(ReceiveContext context)
{
var serviceBusContext = (ServiceBusReceiveContext)context;
var requestActivity = new Activity("Process");
requestActivity.SetParentId(serviceBusContext.Properties["Diagnostic-Id"].ToString());
IOperationHolder<RequestTelemetry> operation = _telemetryClient.StartOperation<RequestTelemetry>(requestActivity);
operation.Telemetry.Success = true;
serviceBusContext.Properties.Add(TelemetryOperationKey, operation);
return Task.CompletedTask;
}
On PostReceive I am able to stop operation:
public Task PostReceive(ReceiveContext context)
{
var serviceBusContext = (ServiceBusReceiveContext)context;
var operation = (IOperationHolder<RequestTelemetry>)serviceBusContext.Properties[TelemetryOperationKey];
operation.Dispose();
return Task.CompletedTask;
}
I also do some magic when exception happens:
public Task ReceiveFault(ReceiveContext context, Exception exception)
{
_telemetryClient.TrackException(exception);
var serviceBusContext = (ServiceBusReceiveContext)context;
var operation = (IOperationHolder<RequestTelemetry>)serviceBusContext.Properties[TelemetryOperationKey];
operation.Telemetry.ResponseCode = "Fail";
operation.Telemetry.Success = false;
operation.Dispose();
return Task.CompletedTask;
}
It was difficult to find this solution by reading MassTransit documentation. I would say that MassTransit is a fantastic tool for some situations there is no alternatives. However documentation is pretty poor.
You can use Application Insights with MassTransit, there is a package available that writes metrics directly.
The documentation is available here:
https://masstransit-project.com/advanced/monitoring/applications-insights.html
Also, you can access Activity.Current from anyway, I think, based on my experience with DiagnosticSource. It might be different with AppInsights though.
I have a method hello(HttpServletRequest request) that needs to be unit tested. In this method, I do something like this Cookie cookie = WebUtils.getCookie(request, cookie_name). So basically, I extract the cookie here and do my stuff. This is how my test class looks like:
#Test
public void testHello() {
Cookie cookie = new Cookie(cookie_name, "");
Mockito.when(request.getCookies()).thenReturn(new Cookie[]{cookie});
Mockito.when(WebUtils.getCookie(request, cookie_name)).thenReturn(cookie);
// call the hello(request) and do assert
}
So whenever I try to mock and return this cookie, I end up with something like this in my stack trace.
org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
Cookie cannot be returned by getCookies()
getCookies() should return Cookie[]
***
If you're unsure why you're getting above error read on.
Due to the nature of the syntax above problem might occur because:
1. This exception *might* occur in wrongly written multi-threaded tests.
Please refer to Mockito FAQ on limitations of concurrency testing.
2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies -
- with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.
Inside WebUtils.getCookie(), it basically does request.getCookies() and iterates the array to get the correct one. This WebUtils comes from Spring Web. As you can see I have returned some value for that as well. Still getting this error. Has anyone faced this issue? How can I workaround this?
Following up on #Ajinkya comment, I think this is what he wanted to express:
The getCookie method might looks something like this (I just used some version of it, so there might have been some changes in the version you are using)
public static Cookie getCookie(HttpServletRequest request, String name) {
Assert.notNull(request, "Request must not be null");
Cookie cookies[] = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (name.equals(cookie.getName())) {
return cookie;
}
}
}
return null;
}
Since you mocked your request you can control what getCookies() is returning.
To make this method working (without mocking it), you just would need to return a mock instead of a real Cookie from getCookies().
Cookie mockCookie = Mockito.mock(Cookie.class);
Mockito.when(mockCookie.getName()).thenReturn(cookie_name);
Mockito.when(request.getCookies()).thenReturn(new Cookie[]{mockCookie});
Changing it to this and the static method can do its work as usual. You wouldn't need bother mocking it.
I have a class which is used to perform Validation of Antiforgery tokens where the payload is Json. That class looks like this (from Phil Haacked):
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class ValidateJsonAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
if (ReferenceEquals(filterContext, null)) throw new ArgumentNullException("filterContext");
var request = filterContext.HttpContext.Request;
// Only validate POSTs
if (request.HttpMethod == WebRequestMethods.Http.Post)
{
// Ajax POSTs and normal form posts have to be treated differently when it comes
// to validating the AntiForgeryToken
if (request.IsAjaxRequest())
{
var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];
var cookieValue = ReferenceEquals(antiForgeryCookie, null) ? null : antiForgeryCookie.Value;
AntiForgery.Validate(cookieValue, request.Headers[AntiForgeryConfig.CookieName]);
}
else
{
new ValidateAntiForgeryTokenAttribute().OnAuthorization(filterContext);
}
}
}
}
This is the first Angular project I am using it on and it is not throwing an exception where I would expect it to. For example, the value in the header differs from the value in the cookie and the call to AntiForgery.Validate proceeds without exception.
The anti-forgery token is rendered in the shell view (i.e. Index.cshtml) and it is added to the headers in Angular's module run function:
// Handle routing errors and success events
theApp.run(['$http', '$route', '$rootScope', '$q', 'routeOverlord',
function ($http, $route, $rootScope, $q, routeOverlord) {
// Include $route to kick start the router.
routeOverlord.setRoutingHandlers();
// Include AntiForgeryToken to prevent CSRF attacks
$http.defaults.headers.common['__RequestVerificationToken'] = angular.element('input[name="__RequestVerificationToken"]').val();
}]);
Is this a known thing? Happy to provide a Fiddler screenshot of the differing strings in the cookie and header if requested.
Cheers
The cookie token and the form token (the one in the headers in your case) are not supposed to be identical (it would be easier to fake).
The cookie token contains a random blob. The form token contains the same blob, plus some identity data (and optionally some additional data).
AntiForgery.Validate() checks that both blobs are identical, and that the other data in the form token corresponds to the identity data and the optional additional data.
I have seen this as well. The cookie value and the field value being different but the .Net framework still letting them through.
This is because the .Net Framework's implementation is a little more complicated then a simple value matching check.
After looking over the source code on Github, see that the tokens contain additional information besides just a GUID (they are tying it to the current user).
I can see form the TokenValidator that the cookie value is a token representing a SessionToken where the field value (your header value) is not expected to be a session token.
// Do the tokens have the correct format?
if (!sessionToken.IsSessionToken || fieldToken.IsSessionToken)
{
throw HttpAntiForgeryException.CreateTokensSwappedException(_config.CookieName, _config.FormFieldName);
}
But the pair of them are still used to verify the action did come from the authorized user and not some precanned attack from a malicious person.
I personally need to do more studying of Microsoft's implementation, but from the little bit I see right now (and linked below) the values should most certainly be different.
References I looked at:
AntiXsrf AntiForgery
AntiXsrf AntiForgeryWorker
AntiXsrf TokenValidator
AntiXsrf AntiForgeryTokenSerializer
I am currently building a web api service using MVC and I am creating the endpoints. For example, my GET endpoint will execute a stored procedure and return the data in JSON format. The model of the data returned can vary in the future and it seems like using a dynamic return type would remove the need of having to change the model and mapping every time that happens. Basically, here is some sample code, do you notice any malpractices in my implementation?
[System.Web.Mvc.HttpGet]
[Route("companies/{id}")]
public dynamic GetCompany([FromUri] int id, string userId)
{
var parameters = new Hashtable
{
{"UserID", userId},
{"CompanyID", id}
};
var result = MyDB.ExecuteSp(CompanyReadByIdSp, parameters);
return result;
}
In fact, this would enable me to transform the object and add whatever I want to it without needing to worry about the model. Is this a bad way of doing things? Thanks ahead.
Can I write something like the following (in an assembly being used in an ASP.NET web page)?
public static string CurrentAuthenticatedUserFromHttpRequest
{
get
{
if (HttpContext.Current.Items["AuthUser"] == null)
{
return string.Empty;
}
return HttpContext.Current.Items["AuthUser"].ToString(); //set in "TryAuthenticate"
}
}
It is going to be a static read-only property. The value (to HttpContext.Current.Items["AuthUser"]) is set through a httphandler.
Just wondering on how this would perform during multiple requests. Is the data going to be accurate when multiple users try to access the same property (in multiple requests), even when high volumes of requests come in?
Yes, this is threadsafe. The static HttpContext.Current property differs per thread and contains the context for the request that the thread is currently handling.