In case if user works with web application via web browser, the user's session is managed by application server. It takes care of sessions creation, validation, timeouts, disposings, etc.
And as far as I know there is no such mechanisms in the other case, if user works with app via remote client and uses SOAP web services.
So the question is, how can we manage users' sessions in case of web services and implement the same mechanisms of session management such as invalidation, prolongation, disposing?
Assuming you use JAX-WS and SOAP/HTTP it is possible to work with container managed security (and e.g. session cookies) as well. You just have to inject WebServiceContext in your service. It allows access to all HTTP environment variables:
#Resource
WebServiceContext wsContext;
A detailed example is available here. Of course, your clients must support this as well (if they are JAX-WS based it works). Nevertheless, a rule of thumb is that web services should not maintain any state at all, they should behave stateless. See this on SO.
Edit: You can access the ServletRequest by:
#WebMethod
public void foo() {
final MessageContext mc = this.wsContext.getMessageContext();
final ServletRequest sr = mc.get(MessageContext.SERVLET_REQUEST);
/* works if this is a HTTP(s) request */
if (sr != null && sr instanceof HttpServletRequest) {
final HttpServletRequest hsr = (HttpServletRequest) sr;
hsr.getSession(true);
/* ... */
} else {
/* do some exceptional stuff */
}
}
The session created above should behave in exactly the same way as a 'standard' web session. You must make sure that your clients understand that as well. They have to submit the session identifier (cookie) on each subsequent call.
I think you are talking about how to maintain web-services session(state-full web-services).
In this case following link can help you:
https://blogs.oracle.com/sujit/entry/ws_addressing_and_stateful_webservice
Web Service does not support session state for achieving high scalability, web service is designed stateless.
Session state handling is not a part of SOAP specification. The cookie stores a token which acts as session identifier. There are a number of ways to pass the session identifier: as an HTTP cookie, as a SOAP header, or as an element in the SOAP message body.
A SOAP header is transport independent, but it requires the SOAP client and service to agree on the format of the SOAP header, and it required that both the SOAP client and SOAP server implementations support SOAP headers. If you use the SOAP body to pass the session id, then it's up to the service (i.e., your application code) to re-establish the state on each call. Stateful processing can make cross-SOAP interoperability a bit more challenging, but it does work. Check into the capabilities of your SOAP implementation. source
Related
As restful service stateless, it don't maintain any interaction of user, so i want to know if multiple user accessing same restful service, then how restful service identify which user interact with which method ? and is it possible to make restful service as stateful ?
Which user:
By using a shared secret (a line of chars), created on the server, and returned with every next request.
It's "saved" in a cookie and returned by the client, using either a cookie or a HTTP(S) header.
Which method:
This depends on the framework you use. But eventually it comes down to mapping URI's to your methods.
and is it possible to make restful service as stateful ?
You can make stateful apps, then they are not restful. A restful app is stateless. That's the definition, so you can make stateful apps, but you can never create a stateful rest-app, as rest is stateless.
tl;dr
The client must store its own session state and pass it around to the server in each request.
The stateless constraint
The stateless constraint of the REST architectural style is define as follows:
5.1.3 Stateless
[...] each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server. Session state is therefore kept entirely on the client. [...]
Authentication
If the client requests protected resources that require authentication, every request must contain all necessary data to be properly authenticated/authorized. See this quote from the RFC 7235:
HTTP authentication is presumed to be stateless: all of the information necessary to authenticate a request MUST be provided in the request, rather than be dependent on the server remembering prior requests.
And authentication data should belong to the standard HTTP Authorization header. From the RFC 7235:
4.2. Authorization
The Authorization header field allows a user agent to authenticate itself with an origin server -- usually, but not necessarily, after receiving a 401 (Unauthorized) response. Its value consists of credentials containing the authentication information of the user agent for the realm of the resource being requested. [...]
The name of this HTTP header is unfortunate because it carries authentication instead of authorization data.
For authentication, you could use the Basic HTTP Authentication scheme, which transmits credentials as username and password pairs, encoded using Base64:
Authorization: Basic <credentials>
If you don't want to send the username and password in each request, the username and password could be exchanged for a token (such as JWT) that is sent in each request. A JWT token can contain the username, an expiration date and any other metadata that may be relevant for your application:
Authorization: Bearer <token>
See this answer for more details.
According to my point of view Restful web service make as a stateless.it's architectural style which have set of constraints and properties so stateless is its properties we cannot change its properties so its doesn't mean that restful service is stateful .
we can mapped URI's to your method then restful know which user is calling which method.
I'm trying to build a login screen for my GWT app. When you click the login button, the credentials (username & password) need to be sent to the server for authentication. I'm wondering what server communication method is a best fit for this: GWT-RPC or RequestFactory.
My understanding is the RequestFactory is more efficient and recommended over GWT-RPC, but it's more of a data/entity/persistence framework than a request-response framework like RPC. So although many GWT afficionados recommend using RequestFactory over GWT-RPC, I don't think RequestFactory can be used for this scenario. After all, I don't want to CRUD a login request, I want to send credentials to a server, perform secured authentication, and return a response to the client.
Am I correct? Is GWT-RPC my only option? or
Can RequestFactory be used. If so, how (need to see a code example of both client and server code)?
You can use either, although RF is very used with EntityProxy, it also is thought to work with ValueProxy which mean transmit any type. RF facilitates as well execution of remote procedures passing Proxy types or primitive types.
Said that, I would use the technology used primarily in my app. If you are using RPC send your login/password in a RPC request, but if you are using RF use it, so as you dont mix things, although you can mix RF, RPC, and plain Ajax without problems.
What you have to be aware of, is that normally, in applications requiring authentication you have to use a filter to check whether the user has a valid session when requesting RPC or RF, so in the case of sending a request for login, you have to jump somehow the auth filter.
Related with security, both scenarios are the same, you have to do the request in an https enabled environment.
[EDIT]
This could be the interface for the client and the remote implementation of a RF call for login, as you can see it is really easy, you can add any method you need to these classes:
#Service(value = LoginUserService.class)
public interface LoginUserRequest extends RequestContext {
Request<Boolean> login(String username, String password);
}
public class LoginUserService {
// Using static you dont need to provide a Locator for the service
static Boolean login(String username, String password) {
return true;
}
}
Related with auth filters for RF, you can take a look to this: GWT RequestFactory authentication functions
With both technology you can send such information to server side, but as already you pointed out the RequestFactory is dedicated to entity management. In your case is better to use GWT-RPC because in order to only send the credentials server side, and eventually retrieve the authentication result, you don't need the RequestFactory surplus (delta transmission, entity management).
For authentication, I would (almost) always use RequestBuilder, i.e. a simple HTTP(S!) POST. Why? Because this way you can implement a general authentication mechanism, that can not only be used by GWT apps. You gain the flexibility to add a simple HTML login page, single sign-on, standard server-side mechanisms (e.g. Spring security), etc.
A simple GWT re-login dialog is also no problem with RequestBuilder - to submit just username/password, GWT-RPC or RF is simply not necessary.
In PHP when a user logs into her account, I do the following in order to remember the user as she navigates through the site:
session_start();
...
$_SESSION['username'] = $username;
On any other page that may require sensitive data, I check that $_SESSION['username'] is valid.
When a use logs out, I do the following
unset($_SESSION['username']
session_destroy();
How do I do the same thing in Java? I have a REST API which uses Jersey and EJB. In case the following is important, I am persisting with JPA, Hibernate, Glassfish, and mysql.
UPDATED FOR VERIFICATON:
Is this correct?
#Path("login")
public class UserLoginResource {
#EJB
private LoginDao loginDao;
#Context
HttpServletRequest request;
#POST
public Response login(JAXBElement<Login> jaxbLogin){
Login login = jaxbLogin.getValue();
loginDao.authenticateUserLogin(login);
HttpSession session = request.getSession();
session.setAttribute("username", login.getUsername());
return Response.ok().build();
}
}
Java is very different from php, so in java You will get session from only HttpRequest 's getSession() method, In php it is all time assumed, your code is run by some server(ie apache), In java, you will obtain it from ServletContainer(ie Apache Tomcat).
You do not have to start session in java unlike php, As long as you are in servlet container and giving request, for this client servlet container is responsible to start if there is not session for it
So for above actions:
reqest.getSession().setAttribute("udername","Elbek");
//later
reqest.getSession().removeAttribute("udername");
//destroy it
reqest.getSession().invalidate();
Here request is object of HttpRequest class
You may have a look to this HttpSession
I strongly recommend you to have a look java scopes
There is not this kind of thing in php, I wish there is, BUT there is NO
Here is how you get request object into your jersey action(method), ie by injecting #Context HttpServletRequest httpRequest
EDIT:
You do not create HttpRequest object by yourself, Instead you will get it from servlet container, Your server creates it from clients request and gives for your.
+elbek describes plain servlet situation - however, nowadays almost nobody writes plain servlet. It sickes soo much back then, that a lot of web frameworks evolved. There is a sh*tload of them, but good ones will utilize dependency injection techniques like spring
( for example , struts 2 ) and there are distinct scopes - application / session / request - containing plain java beans, which can in turn have authentication data.
J2EE also provides own authentication semantics with servlet container and JAAS - it also uses session tracking and useful when you need to access some backend resources like datasources or queues or EJBs - but most web application do not bother wth it.
My setup is as follows
A main application servlet accessible under /myApp/mainServlet/
A little "hand made" soap proxy that adds security headers (usernames, passwords) to soap calls coming from a client
A Flex client that talks to the main servlet (through a BlazeDS interface), and sends some soap calls to a third party through this soap proxy
The flex client has a session id which is set when it first talks to the main servlet and it returns a HTTP header such as "Set-Cookie: "JSESSION: something; Path=/myApp". This cookie is then sent the the server to inform of which session the client is associated to.
The problem is that the little soap proxy also returns a cookie with a session id (for each call made through it) - and the Flex client then uses these cookies when talking to the main servlet. These other session ids are unknown to it, and then of course nothing works ...
I do not want a session cookie to be returned from the soap proxy, and I have verified that the problem would be solved by doing so by telling an Apache front-end to strip all "Set-Cookie" headers coming from the soap proxy. Unfortunately (due to some setup restrictions), this is not a way I can go in production, and so I will need to fix it programmatically.
How can I make the servlet not try to set any session ids? I believe I have seen ways of telling Jetty (the app server) not to send sessions ids, but that would also affect the main servlet's ability to do so as well, and is also not portable.
The proxy servlet is a very basic Spring Controller (just implementing the interface), so basically just a bare bone servlet.
Removing the cookie can be done with res.setHeader("Set-Cookie", null);
Edit: It is good to know, that this removes all cookies, since they are all set in the same header.
I recommend that you don't do it in your servlet, a Filter is better, because it's less intrusive, something like:
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException
{
HttpServletResponse res = (HttpServletResponse) response;
try
{
chain.doFilter(request, res);
}
finally
{
res.setHeader("Set-Cookie", null);
}
}
This solution is inspired by this article at randomcoder.
I'm fairly new to writing web services. I'm working on a SOAP service using JAXWS. I'd like to be able to have users log-in and in my service know which user is issuing a command. In other words, have some session handling.
One way I've seen to do this is to use cookies and access the HTTP layer from my web service. However, this puts a dependency on using HTTP as the transport layer (I'm aware HTTP is almost always the transport layer but I'm a purist).
Is there a better approach which keeps the service layer unaware of the transport layer? Is there some way I can accomplish this with servlet filters? I'd like the answer to be as framework agnostic as possible.
I'm working on a SOAP service using JAXWS. I'd like to be able to have users log-in and in my service know which user is issuing a command. In other words, have some session handling.
Conventional Web services are stateless in nature, there is no session handling in web services (which has by the say nothing to do with identifying the caller).
If you want to require your users to be authenticated to call a service, the traditional approach is to:
Expose an "authentication" web service (passing user credentials) that returns an authentication token.
Have the users call this authentication first.
Have the users pass the token in a custom header on subsequent calls of "business" web services.
On the server side:
Reject any call that doesn't contain a valid token.
Invalidate tokens after some time of inactivity
You can implement a custom solution for this approach (this is a highly interoperable solution). Or you can use WS-Security/UsernameTokens that provides something similar out of the box. WS-Security is a standard (Metro implements it), it isn't "framework" specific.
As you mention, servlet filters can provide the basis of solution. Use a filter to store the current session details (e.g. the session context Map) in a threadLocal storage. This is implemented as your application class, so is transport agnostic. Your service simply uses a static method to fetch the current context, unaware of where it came from.
E.g.
class ServiceSessionContext
{
static ThreadLocal<Map> local = new ThreadLocal<Map>();
// context set by the transport layer, e.g. servlet filter
static public void setContext(Map map)
{
local.put(map);
}
// called when request is complete
static public void clearContext()
{
local.put(null);
}
// context fetched by the service
static public Map getContext()
{
return local.get();
}
}