I currently have a webclient class that maintains session for my web application using session variables but I want to instead use cookies to maintain session. I of course don't have access to the ASP.NET Response and Request variables in this class. Would I have to pass those objects to the webclient class?
Not sure what are you trying to achieve, but in any of your custom classes inside of ASP.NET application you can access Request and Response via
HttpContext.Current.Request
and
HttpContext.Current.Response
As Yuriy pointed out you could access the request/response objects directly via the HttpContext.Current namespace, this however is bad practice. Your class has a dependency on the request/response objects, these should be passed into your class via it's constructor.
e.g.
public class SessionExample{
public SessionExample(System.Web.HttpRequest request, System.Web.HttpResponse response){
}
}
Or if your class is meant to live for longer than the duration of a single http request you can pass them in as method paramaters
public class SessionExample{
public SessionExample(){
}
public void DoSomething(System.Web.HttpRequest request, System.Web.HttpResponse response){
}
}
Structuring your code this way makes it more testable and will save you headaches down the road.
Related
I am looking for a solution related to passing cookies values from JAX-RX REST API endpoint to ejb layer.
I tried searching the solution and found some of them are using thread local. but and thread local supposed to be not working with executor services.
Is there any another solution that I can use to pass cookies values from web/rest later to ejb layer.
Note: I do not want to pass it as method parameter from rest layer to down the ejb layer. I would like to access the cookies values directly in ejb layer
Thanks
Lets say you have a class MyEJB, you can inject HttpServletRequest object to you ejb as follows:
public class MyEJB{
#Context
private HttpServletRequest httpRequest;
}
Now from this request object you can access your required cookies. As follows:
String rawCookie = request.getHeader("Cookie");
String[] rawCookieParams = rawCookie.split(";");
for(String rawCookieNameAndValue :rawCookieParams)
{
String[] rawCookieNameAndValuePair = rawCookieNameAndValue.split("=");
}
In a raw Spring WebSocket application (not using sockjs/STOMP or any other middleware), how can I have Spring inject beans that have been registered in the HTTP session scope so that they can be used by code in my WebSocketHandler bean?
Note that what I am not asking is any of these questions:
How do I create beans in a scope that is accessible to all handler invocations for the same WebSocket session (e.g. as described in the answer to Request or Session scope in Spring Websocket). The beans I need to access already exist in the scope for the HTTP session
How do I (programatically) access objects in the servlet container's HTTP session storage (I haven't tried to do this, but I'm pretty sure the answer involves using an HttpSessionHandshakeInterceptor), but that doesn't get me injection of Spring scoped dependencies.
How to use a ScopedProxy to pass beans between code in different scopes (e.g. as described here); I'm already familiar with how to do this, but attempting to do so for a WebSocketHandler causes an error because the session scope hasn't been bound to the thread at the point the object is accessed.
How to access the current security principal -- again, very useful, but not what I'm currently trying to achieve.
What I'm hoping to do is provide a simple framework that allows for the traditional HTTP-request initiated parts of an MVC application to communicate directly with a WebSocket protocol (for sending simple push updates to the client). What I want to be able to do is push data into a session scoped object from the MVC controller and pull it out in the websocket handler. I would like the simplest possible API for this from the MVC controller's perspective, which if it is possible to just use a session-scoped bean for this would be ideal. If you have any other ideas about very simple ways of sharing this data, I'd also like to hear those in case this approach isn't possible.
You can also use Java API for websocket. This link https://spring.io/blog/2013/05/23/spring-framework-4-0-m1-websocket-support
explains how to do this with Spring.
Ufortunately, something like this
#ServerEndpoint(value = "/sample", configurator = SpringConfigurator.class)
public class SampleEndpoint {
private SessionScopedBean sessionScopedBean;
#Autowired
public SampleEndpoint(SessionScopedBean sessionScopedBean) {
this.sessionScopedBean = sessionScopedBean;
}
}
causes exception (because we're trying to access bean outside its scope), but for singleton and prototype beans it works well.
To work with session attributes you can modify the hanshake and pass required attributes:
public class CustomWebSocketConfigurator extends SpringConfigurator {
#Override
public void modifyHandshake(ServerEndpointConfig config,
HandshakeRequest request,
HandshakeResponse response) {
//put attributes from http session to websocket session
HttpSession httpSession = (HttpSession) request.getHttpSession();
config.getUserProperties().put("some_attribute",
httpSession.getAttribute("some_attribute_in_http_session"));
}
}
P. S. More a comment than an answer. I just wanted to add another way of handling session attributes in websocket to your question-answer. I have been searching the web for exactly the same issue and the way showed above seems to me the most systematic approach to handling the session data in websocket.
I have an interceptor that checks the ldap group membership of a user and if it's deemed wrong will redirect to a NoAuthorisation page like so:
public class MyIntercept implements HandlerInterceptor {
public boolean preHandle (HttpServletRequest request, HttpServletReaponse response, Object handler) {
If ( // check access) {
response.redirect(/NoAuthorisation?reason=Blablabla);
return false;
}
return true
}
}
This works but I'd like to send the reason in a more not so obvious fashion (not in url)
I was thinking I call the NoAuthorisation controller directly but don't know how to do that.
Any advise and best practices?
SpringMVC has a concept of Flash. It is a way to simply pass arbitrary attributes to a redirected request with 2 characteristics:
you do not use the URL
you are not limited to strings
It is very simple to use in #RequestMapping annotated controllers, since you simply pass a RedirectAttributes parameter to the controller method, populates it and return a redirect:... string.
It can be used in an interceptor but you must explicitely require the output flash map with static methods from RequestContextUtils.
public boolean preHandle (HttpServletRequest request, HttpServletReaponse response, Object handler) {
If ( // check access) {
Map<String, Object> flash = RequestContextUtils.getOutputFlashMap(request);
// populate the flash map with attributes you want to pass to redirected controller
response.redirect(/NoAuthorisation?reason=Blablabla);
return false;
}
return true
}
}
Extract from Spring reference manual:
Flash attributes provide a way for one request to store attributes intended for use in another. This is most commonly needed when redirecting — for example, the Post/Redirect/Get pattern. Flash attributes are saved temporarily before the redirect (typically in the session) to be made available to the request after the redirect and removed immediately.
...
Flash attribute support is always "on" and does not need to enabled explicitly although if not used, it never causes HTTP session creation. On each request there is an "input" FlashMap with attributes passed from a previous request (if any) and an "output" FlashMap with attributes to save for a subsequent request. Both FlashMap instances are accessible from anywhere in Spring MVC through static methods in RequestContextUtils.
... after the redirect, attributes from the "input" FlashMap are automatically added to the Model of the controller serving the target URL.
You could get the Session from the request and put a reason on the session as session parameter and get it back from the session at your redirect endpoint.
Don't forget to clean your session as soon as possible though.
Is good idea to get user identity in ASP.NET Web API controller constructor, for example:
public PagesController(PageValidator pageValidator, PageMapper pageMapper, PagesManager pagesManager, UsersManager usersManager)
:base(usersManager)
{
_pageValidator = pageValidator;
_pageMapper = pageMapper;
_pagesManager = pagesManager;
if (User.Identity.IsAuthenticated)
_pagesManager.UserId = usersManager.GetByEmail(User.Identity.Name).Id;
}
Is always User.Identity was correct populated before this call raise?
This has bitten me a few times. Depending on where/how you are performing your authentication, you need to be careful where you access your identity, particularly in controller constructors.
For example, whilst the controller action is invoked AFTER an IAuthenticationFilter is instantiated, the controller's constructor is called before AuthenticateAsync; meaning any authentication you do in AuthenticateAsync will not be available in your controller's constructor (like in your example).
I typically don't rely on things being available during controller construction (unless handled by DI). Instead access the identity as you need it in your controller actions.
If you are looking at making identity lookup easier (i.e. pulling in your user object based on the User.Identity.Name property) create a base controller class that has a property or method that does it for you, then have your controllers inherit from that...
public User AuthenticatedUser
{
get
{
if (User.Identity.IsAuthenticated)
{
return usersManager.GetByEmail(User.Identity.Name);
}
return null;
}
}
EDIT
See here for a detailed breakdown of the Web.API lifecycle, showing controller creation occurring prior to authentication.
Yes. You can use this property in Controller in any place. ASP.NET has request pipeline: (http://www.dotnetcurry.com/aspnet/888/aspnet-webapi-message-lifecycle).
As you can see Authorization is early stage step in request pipeline.
Controller creation is the latest stage.
please tell me why IHttpHandler need to implement IRequiresSessionState. without implementing it we can not read/write anything in session variable?
can't we access directly HttpContext.Current.session like this way.
please explain.......thanks
public class MyHttpHandler : IHttpHandler, IRequiresSessionState
{
public void ProcessRequest(HttpContext context)
{
var MyValue = context.Session["MyKey"] as String;
MyValue = "Hello World";
context.Session["MyKey"] = MyValue;
}
public bool IsReusable
{
get { return true; }
}
}
The session state is not a native part of the HTTP infrastructure. This means that the request will need to serialize/load the session information (either from memory or database or another server) for requests that need access to session and save it back when done.
HttpHandler is a the process (frequently referred to as the "endpoint") that runs in response to a request made to ASP.NET http runtime. It is used to handle a particular type of object/class/resource as you define it. If processing of that resource does not need access to session, that particular request does not need to go through the loading/saving of session data unnecessarily. So, by default, session is not available for HTTPhandlers, unless it is a predefined handler like Page handler.
To successfully resolve any call to the Session object, the runtime environment must add the session state to the call context of the request being processed, which is IRequireSessionState in this case.
Check out this msdn link for more details.
To answer your question, no, if you dont implement the IRequireSessionState, you will not have access to the session objects in your handler class due to the above mentioned facts.
If you do not implement this interface you should not be able to successfully use the session object. You are supposed to use this interface if you want access to the session, regardless of how you access it.
It shouldn't work without it. If it does, its a fluke and don't rely on it.
The ASP.NET SessionStateModule will not populate the context's session properties unless the handler is marked with the IRequiresSessionState interface.