i am new to Servicestack. I am having MVC4 application and servicestack application deployed on diffrent servers .
I want to use the servicestack session without authentication with MemoryCacheClient.
i am not able to understand the explanation given in
https://github.com/ServiceStack/ServiceStack/wiki/Sessions
I want to check if session is there for each request and if seesion is null create new session with custom value as user id.
My configure method is as followes
public override void Configure(Container container)
{
// in global request filter check if session exists
this.GlobalRequestFilters.Add((req, res, requestDto) =>
{
//check if session exists
var sessionId = req.GetSessionId();
if (sessionId == null)
{
//if no populate session with user defined data ( user id from requestDto)
}
else
{
//how to get the values from session ?
}
}
Please help .
Thanks in advance
The SessionFeature already registers their own Global Request Filter to automatically create missing Temporary or Permanent Session Ids (i.e. ss-id or ss-pid).
It sounds like you want to register a Custom AuthEvent to respond to different events in the session lifecycle, i.e. IAuthEvents.OnCreated().
Related
I'm using spring-session and I really like it. However I think I'm missing something. In my application the flow goes like this:
1) User requests HomepageController and that controller tries to put an attribute in the request:
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
final String sessionIds = sessionStrategy.getRequestedSessionId(request);
if (sessionIds != null) {
final ExpiringSession session = sessionRepository.getSession(sessionIds);
if (session != null) {
session.setAttribute("attr", "value");
sessionRepository.save(session);
model.addAttribute("session", session);
}
}
As you can see it will try to get the sessionID from the request-cookie, and if there's a session with that ID in the repository than use it (add attribute). This is perfect, but only after the second request. Why? Because if I restart the server than the cookie is left with the old value, and then the first request will not find the session in the repository. After the response is committed though the cookie will be updated, so the second request will be correct.
And here's the question: what is wrong with my logic and how should one develop the application in order to support the first request too?
BTW, here's a sample application that demonstrates the problem:
https://github.com/paranoiabla/spring-session-issue
If you are wanting to obtain the session, you should not use requested session id. The requested session id is just that...what the browser requests. Some problems with using requested session (some of which you already outlined):
If you clear all your cookies and make a request, then no session is requested by the browser.
As you pointed out if the data store is restarted and is not persistent, then the requested session id is invalid
If the session expires, then the requested session will be invalid
Instead, you should use the session id:
final String sessionIds = request.getSession().getId();
This will use the requested session id if it is valid, otherwise it will create a new session and ensure the session is written to the response (i.e. included in the response as a cookie).
I would say your approach is wrong, your controller does to much and you should be just using the HttpSession for which Spring Session provides support. You shouldn't also be putting the session in the model imho as you should be just accessing the HttpSession. Your application shouldn't know about Spring Session.
Your controller should look like this
#Controller
public class HomepageController {
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(HttpSession session) {
session.setAttribute("attr", "value");
return "homepage";
}
}
if you don't want to force session creation inject the HttpServletRequest and do getSession(false) instead of injecting the HttpSession.
Everything else (storing the session after request handling etc.) will be handled transparently by Spring Session.
I have an Intranet application with Windows authentication set for user authentication which works fine, only problem is that I do not want to say 'Hello, mydomain\user!' but use the user's full display name which I find in the Active Directory.
In fact I want to populate the profile with even more details from our domain, the problem is that I only want to do this AD query only once after the user has been authenticated on his first call to the application. I have all the AD and profile things working, but I do not find a good place to put the code so that it is called exactly once after login. I suspect a custom AuthorizeAttribute might be a way... Any help is greatly appreciated. Thanks!!
Try storing the information in session or within cookies or local storage on the client side.
Well, I finally came up with a solution - can this be considered as a as a valid answer? Basically I wrote a custom AuthorizationFilter and put a flag into the session to do the whole work only once. However I hoped to find an event "User_Authenticated" which is fired only once. But I guess this is more appropriate for Forms authentication.
public class ProfileUpdater : IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
// if there is a profile already in the session we do not update this
Controller controller = filterContext.Controller as Controller;
if (controller != null && controller.Session["ProfileUpdated"] != null)
{
return;
}
else if (controller == null)
{
return;
}
UserPrincipal domainUser = DomainHelper.GetDomainUser(controller.User.Identity.Name);
if (domainUser != null)
{
controller.Profile.SetPropertyValue("DisplayName", domainUser.DisplayName);
controller.Session["ProfileUpdated"] = true; // just put a marker object into the session to show we alreay updated the Profile
}
return;
}
}
Technologies I'm Using:
MVC v2
Forms Authentication (Sliding Expiration)
Session State Server
Custom Authorization Attribute
I'm using the state server process for my mvc app. During testing, when an authenticated user would click the "LogOff" button, it would correctly take them to the authentication screen, and upon successful credential entering, would log them back in. BUT, it would find their prior session variable state, and NOT reload any new permissions I'd given them. This is due to how I'm loading a user in the following code:
public override void OnAuthorization(AuthorizationContext filterContext) {
if (filterContext == null)
throw new ArgumentNullException("FilterContext");
if (AuthorizeCore(filterContext.HttpContext)) {
IUser customUser = filterContext.HttpContext.Session["CustomUser"] as IUser;
if ((customUser == null) || (customUser.Name != filterContext.HttpContext.User.Identity.Name)) {
customUser = new User(filterContext.HttpContext.User.Identity.Name,
filterContext.HttpContext.User.Identity.IsAuthenticated);
}
if (_privileges.Length > 0) {
if (!customUser.HasAtLeastOnePrivilege(_privileges))
filterContext.Result = new ViewResult { ViewName = "AccessDenied" };
}
filterContext.HttpContext.Session["CustomUser"] = customUser;
}
}
So, you can see I'm storing my customUser in the Session and that value is what was fetched from the prior session even though the user had logged off between (but logged back on within the sliding expiration window.
So, my question is, should I place a simple Session.Abandon() call in my LogOff method in the AccountController, or is there a cleaner more advantageous way of handling this?
Normally Session.Clear() should be enough and remove all values that have been stored in the session. Session.Abandon() ends the current session. It might also fire Session_End and the next request will fire Session_Start.
I've a Web App that just recently has began randomly losing sessions. The exact cause is elusive at best, however it seems the session is killed/lost on the server side and results in the user needing to close their browser entirely and relaunch in order to log back in.
I wish I could provide some code, but I can't figure out where the problem is at all.
Here is a session action filter we use currently:
public class SessionExpireAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
HttpContext lvContext = HttpContext.Current;
//if(
// check if session is supported
if (lvContext.Session != null)
{
// check if a new session id was generated
if (lvContext.Session.IsNewSession)
{
// If it says it is a new session, but an existing cookie exists, then it must
// have timed out
string sessionCookie = lvContext.Request.Headers["Cookie"];
if ((null != sessionCookie) && (sessionCookie.IndexOf("ASP.NET_SessionId") >= 0))
{
lvContext.Response.Redirect("~/Account/Timeout");
}
}
}
base.OnActionExecuting(filterContext);
}
}
Did you add a new feature that adds or removes files from the root directory or any of its subdirectories? That can cause the session to reset.
Ultimately I moved to SQL State Server to handle my sessions. This outsources session handling to the SQL server allowing a session to persist through a recycle, etc. For more information see these links:
Session-State Modes
HOW TO: Configure SQL Server to Store
ASP.NET Session State
I am using Http Handler ashx file for showing the images.
I was using Session object to get image and return in the response
Now problem is i need to use custom Session object its nothing but the Wrapper on HttpSession State But when i am trying to get existing custom session object its creating new ...
its not showing session data , i checked the session Id which is also different
Please adive how can i get existing session in ashx file ?
Note: When i use ASP.NET Sesssion its working fine
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class GetImage : IHttpHandler, System.Web.SessionState.IRequiresSessionState
{
When you want to get access to your Session State from an ASHX or HttpHandler you need to implement IReadOnlySessionState or IRequiresSessionState if you need read/write access.
The fact that it's an ashx should be irrelevant - assuming the request is being spawned off a request from an exsiting session; I'm assuming it should be - but it might pay to check exactly how the request is being formed. Always pays to go back to basics :)
Assuming that's ok, this is how I've been doing it:
string sessionId = string.Empty;
System.Web.SessionState.SessionIDManager sessionIDManager = new System.Web.SessionState.SessionIDManager();
bool supportSessionIDReissue;
sessionIDManager.InitializeRequest(httpContext, false, out supportSessionIDReissue); sessionId = sessionIDManager.GetSessionID(httpContext);
if (sessionId == null)
{
// Create / issue new session id:
sessionId = sessionIDManager.CreateSessionID(httpContext);
}
At the end of this the sessionId variable will (should) contain the existing Session ID, or a newly created one that you can reuse later..
you can just use a Actionresult rather than a handler for this
return new FileStreamResult(new FileStream(path, FileMode.Open), "image/jpeg");
or
return(new FileResult(Pathtoimage, "image/jpeg"));
that should make things easier as you wil be using a controll/action as your url
ie
<img src="/Images/showImage/1">
you can then have your actions deal with anything like pulling from db as bytes
streaming, check validation etc