Session atributes missing from spring session when setting inside HttpSessionListener - servlets

In servlet based application I want to make session replication using Spring Session Data Redis. Everything works fine but for csrf security we are using owasp scrfgaurd, where in that flow session token will set at HttpSessionListener.The token is missing while validating.
I tried creating standalone code reproduce the issue.I have created SampleHttpListener and setting some attributes to the session, but these values I am not able to see at servlet level.
Please tell me anything I am missing or any other approach for this senario.
I have added source code here
https://github.com/surya0420/SpringSession

public class CsrfGuardHttpSessionListener implements HttpSessionListener {
#Override
public void sessionCreated(HttpSessionEvent event) {
HttpSession session = event.getSession();
CsrfGuard csrfGuard = CsrfGuard.getInstance();
csrfGuard.updateToken(session);
if(session.getServletContext()!=null){
session.getServletContext().setAttribute(OWASP_CSRFTOKEN,session.getAttribute(OWASP_CSRFTOKEN));
}
}
Since session attributes are missing which are setting at HttpSessionListener level, so I am setting it to
session.getServletContext().setAttribute(OWASP_CSRFTOKEN,session.getAttribute(OWASP_CSRFTOKEN));
after session got created I am setting back the attributes at filter level as shown below at Filter level
if(((HttpServletRequest) request).getSession().getAttribute(OWASP_CSRFTOKEN) == null) {
((HttpServletRequest) request).getSession().setAttribute(OWASP_CSRFTOKEN, request.getServletContext().getAttribute(OWASP_CSRFTOKEN));
}

Related

Handling cookies based on route in a single request lifecycle in ASP.NET MVC?

I'm writing a route that will allow the user to set a cookie with the version of some JSON object that the application will use to set client-side configurations. It is a fairly large JSON object that we don't want to store in a cookie alone. We want to store ONLY the version to be looked up and set from some map up in the cloud on every request since multiple versions of the client are running around and we want those to be separated on a per request basis.
Currently, I know the problem is due to my lack of understanding of the single request lifecycle of ASP.NET MVC as I'm sure the following code proves. I do know that the Application_BeginRequest Action is probably happening BEFORE the route is handled (correct me if I'm wrong here), but I am not sure where it SHOULD be happening so that the cookie is populated BEFORE it is retrieved. I also don't believe that Application_EndRequest would be better due to the same, but opposite issue.
Any and all suggestions that lead to my understanding of the lifecycle and an appropriate Action to handle that kind of cookie value getting will be welcomed!
// Working controller (cookie does get set, this is confirmed)
using System;
using System.Web;
using System.Web.Mvc;
using SMM.Web.Infrastructure.Filters;
namespace SMM.Web.Controllers
{
[NoCache]
public class SetCookieController : ApplicationController
{
private HttpCookie CreateVersionCookie(int versionId)
{
HttpCookie versionCookie = new HttpCookie("version_id");
versionCookie.Value = versionId.ToString();
return versionCookie;
}
public ActionResult SetCookie(int versionId)
{
Response.Cookies.Add(CreateVersionCookie(versionId));
return Redirect("/");
}
}
}
// In Global.asax.cs (this does not work to get the cookie)
private void LoadSomeJsonFromACookie()
{
HttpCookie someJsonThingCookie = HttpContext.Current.Request.Cookies["version_id"];
string jsonVersion = (string)staticVersionCookie.Value;
string json = FunctionToGetSomeJsonThingByVersion(jsonVersion); // This returns a stringified JSON object based on the jsonVersion supplied
dynamic someJsonThing = JsonConvert.DeserializeObject<dynamic>(json);
HttpContext.Current.Items["someJsonThing"] = someJsonThing;
}
protected void Application_BeginRequest(object sender, EventArgs e)
{
RedirectToHttps();
// some other redirects happen here
LoadSomeJsonFromACookie();
}
Application_BeginRequest is the right place. Since in the code, you can see I'm firing a redirect back to root /, it will set the cookie before it ever needs the cookie.

Log visitor data using sessions, or an alternative?

I don't use session state for anything. I've even disabled it in my Web.config, and removed the session module. But, I now need to log visitor data, and don't know how?
I though of doing this:
re-enable session
catch new sessions in void Session_Start(object, EventArgs) method in Global.asax
log stuff of interest
But I'd prefer not to use session state, unless I need to. I recall that sessions are locked by default, which will slow the pipeline.
So how do I log visitor data in ASP.NET MVC without session state?
You use an ActionFilterAttribute
There a how to on the asp.net/mvc site: http://www.asp.net/mvc/overview/older-versions-1/controllers-and-routing/understanding-action-filters-cs
In summary, add a class like:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class LogVisitorsAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var descriptor = filterContext.ActionDescriptor;
var controller = descriptor.ControllerDescriptor.ControllerName;
var action = descriptor.ActionName;
var user = filterContext.HttpContext.User.Identity.Name;
// add your logging here
log(description, controller, action, user);
}
}
You can pull all sorts of interesting "visitor data" during the OnActionExecuting, such as controller/action names (as shown) and the values passed to the action (action parameters).
Then you can either add this to individual actions
[LogVisitors]
public ActionResult Index()
or the controller (or a base controller)
[LogVisitors]
public class HomeController
or to all actions and controllers by adding it to your FilterConfig (which should already exist)
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new LogVisitorsAttribute());
}
}
So how do I log visitor data in ASP.NET MVC without session state?
The simple way is, don't log it. Let a 3rd party log it for you. You could use a free service such as Google Analytics or a paid service such as Hitslink to monitor everything about your users, and have many charting options to analyze the data later.
Then you don't need to have session state, worry about storage for the data, or have to build your own reporting solution to analyze it.
I thought of another way, but it's messy:
intercept in Application_BeginRequest() method in Global.asax
compare a cookie to current time
if >20 minutes then it's a new session, else update cookie with current timestamp
if new session then perform logging
Cons:
fires for every request
reinventing the wheel - this is basically session state!
Pros:
Lighter than session state
doesn't lock anything
Hope there's a better way, as this seems messy.

Access UserDetails object in Websocket session Spring MVC

In a call sent over a websocket connection in a Spring MVC 4 application, I can get a java.security.Principal object when adding this as a parameter in the method.
However, this basicly only has the username in it, and I need the (extended) UserDetails object created during logging in.
SecurityContextHolder.getContext().getAuthentication() returns null. As I understood because spring creates a special session for handling the websocket connections.
The Question: Is there a way to access the securitycontext from inside the websocket session/thread?
(Being able to access a session bean would suffice as well).
#AuthenticationPrincipal is specifically for REST/MVC methods.
However, you can get pretty close by adding an argument of Type java.security.Principle to your #MessageMapping annotated method and then taking the real UserDetails object from it as follows:
FooUserDetails currentUser = (FooUserDetails) ((Authentication) user).getPrincipal();
This works for me for Spring Boot 1.5.4
I suppose you have extended AbstractWebSocketHandler
the you could have principal name :
#Override
public void afterConnectionEstablished ( WebSocketSession session ) throws Exception {
logger.info ( "afterConnectionEstablished = " + session.getPrincipal () );
}
I've not tested it, but you should be able to access your user adding a parameter like
#AuthenticationPrincipal CustomUser customUser
to your #MessageMapping method.
You can find more here: http://docs.spring.io/spring-security/site/docs/4.0.x/reference/htmlsingle/#mvc-authentication-principal

How do I set query cache on a call issued by the seam engine

#In
Identity identity;
Boolean newValue = identity.hasPermission(target, action);
Any call to the above method also does a "select role from Role r" call, which is called from the underlying seam engine. How do I set the query cache for this call as a query hint (e.g. org.hibernate.cacheable flag) so that it doesn't get called again.
Note: Role information is never bound to change, hence I view this as a unnecessary sql call.
I am not in hibernate, but as this question is still unanswered: we extended the standard Identity class of seam for several reasons. You might want to extend it as well to help you caching the results.
As this cache is session scoped, it will have the possible benefit that it will be reloaded when the user logs on/off again - but this depends on your requirements.
Best regards,
Alexander.
/**
* Extended Identity to implement i.e. caching
*/
#Name("org.jboss.seam.security.identity")
#Scope(SESSION)
#Install(precedence = Install.APPLICATION)
#BypassInterceptors
#Startup
public class MyIdentity extends Identity {
// place a concurrent hash map here
#Override
public boolean hasPermission(Object name, String action) {
// either use the use the cached result in the hash map ...
// ... or call super.hasPermission() and cache the result
}
}

ASP.NET Object Caching in a Class

I'm trying to create a Caching Class to cache some objects from my pages. The purpose is to use the Caching system of the ASP.NET framework but to abstract it to separate class.
It seems that the caching doesn't persist.
Any ideas what I'm doing wrong here? Is it possible at all to cache object out side the Page it self?
EDIT: added the code:
Insert to cache
Cache c = new Cache();
c.Insert(userid.ToString(), DateTime.Now.AddSeconds(length), null, DateTime.Now.AddSeconds(length), Cache.NoSlidingExpiration,CacheItemPriority.High,null);
Get from the cache
DateTime expDeath = (DateTime)c.Get(userid.ToString())
I get null on the c.Get, even after I did have the key.
The code is in a different class than the page itself (the page uses it)
Thanks.
There are numerous ways you can store objects in ASP.NET
Page-level items -> Properties/Fields on the page which can live for the lifetime of the page lifecycle in the request.
ViewState -> Store items in serialised Base64 format which is persisted through requests using PostBack. Controls (including the page itself - it is a control) can preserve their previous state by loading it from ViewState. This gives the idea of ASP.NET pages as stateful.
HttpContext.Items -> A dictionary of items to store for the lifetime of the request.
Session -> Provides caching over multiple requests through session. The session cache mechanism actually supports multiple different modes.
InProc - Items are stored by the current process, which means should the process terminate/recycle, the session data is lost.
SqlServer - Items are serialised and stored in a SQL server database. Items must be serialisable.
StateServer - Items are serialised and stored in a separate process, the StateServer process. As with SqlServer, items must be serialisable.
Runtime - Items stored in the runtime cache will remain for the lifetime of the current application. Should the applciation get recycled/stop, the items will be lost.
What type of data are you trying to store, and how do you believe it must be persisted?
Right at the beginning of last year I wrote a blog post on a caching framework I had been writing, which allows me to do stuff like:
// Get the user.
public IUser GetUser(string username)
{
// Check the cache to find the appropriate user, if the user hasn't been loaded
// then call GetUserInternal to load the user and store in the cache for future requests.
return Cache<IUser>.Fetch(username, GetUserInternal);
}
// Get the actual implementation of the user.
private IUser GetUserInternal(string username)
{
return new User(username);
}
That was nearly a year ago, and it has been evolved a bit since then, you can read my blog post about it, let me know if thats of any use.
Your cache reference needs to be accessible to all items in your code - the same reference.
If you are newing up the Cache class every time, you are doing it wrong.
I have done almost the same things, but with a different code (and it work for me) :
(CacheKeys is an enum)
using System;
using System.Configuration;
using System.Web;
using System.IO;
public static void SetCacheValue<T>(CacheKeys key, T value)
{
RemoveCacheItem(key);
HttpRuntime.Cache.Insert(key.ToString(), value, null,
DateTime.UtcNow.AddYears(1),
System.Web.Caching.Cache.NoSlidingExpiration);
}
public static void SetCacheValue<T>(CacheKeys key, T value, DateTime expiration)
{
HttpRuntime.Cache.Insert(key.ToString(), value, null,
expiration,
System.Web.Caching.Cache.NoSlidingExpiration);
}
public static void SetCacheValue<T>(CacheKeys key, T value, TimeSpan slidingExpiration)
{
HttpRuntime.Cache.Insert(key.ToString(), value, null,
System.Web.Caching.Cache.NoAbsoluteExpiration,
slidingExpiration);
}
public static T GetCacheValue<T>(CacheKeys key)
{
try
{
T value = (T)HttpRuntime.Cache.Get(key.ToString());
if (value == null)
return default(T);
else
return value;
}
catch (NullReferenceException)
{
return default(T);
}
}

Resources