what is current subject in Shiro? - java

I'm new to Shiro and got confused about the current subject concept:
Subject subject = SecurityUtils.getSubject(); // gets the current subject
subject.login(...); // do login
subject.logout(); // do logout
In my application I need to run work from different users concurrently, thus multiple users(subjects) co-exist concurrently, new users login and old users logout on the fly: clients sends work with [username, password] to server, the server do credential check by Shiro with the given [username, password], if [username, password] not exist in database, reject the work, if exist, login and dispatch the work to be processed, in the meanwhile other clients sends their work and login, my question is in a later time when the work for a user is done and I need to logout out the user, how do I get the subject for it?

SecurityUtils.getSubject() returns the subject bound to the current thread (typical web app pattern), the source of the session is typically from information in a Http Session or Http Request. (Shiro is NOT bound to the Servlet API, it is just a really common model). So in the context of your application, the request might be just some method call containing the current User/Subject (not sure how your application makes this association or authenticates them, but that is a different question). This means you may not need to use SecurityUtils.getSubject().
Once you have a Subject and if you want to use SecurityUtils.getSubject() elsewhere in your code, you could wrap the call in a Callable: https://shiro.apache.org/subject.html#automatic-association (this is basically what Shiro's Servlet module does)

Related

WebSockets - correct approach for creating channels and pushing data

I have a scenario whereby I want to inform users of my site that someone has commented on an article on which they have also commented. This is a lot like the way that SO notifies me when someone responds to a question!
Server side, I persist the comment and then look up all users who commented on the same article. I then broadcast (I'm using Atmosphere):
PushContext pushContext = PushContextFactory.getDefault().getPushContext();
for(User u : users){
// channel name, message
pushContext.push("/user_" + u.id, "someone commented! blah blah");
}
The "channel" I am broadcasting to is the user's "own" channel, since I don't want every user to be notified. I use the user's ID in the channel name to achieve this.
Is this the right way to do ensure only relevant users get notified?
I guess I also want to do two more things:
Only push to users whom I believe are still online. If they aren't online, then it's a waste of resources pushing to them.
Encrypt the message, because otherwise anybody could listen for my messages, if they know my user ID.
Is there anything else I need to think of?
SO uses WebSockets, for example when a comment is made on this posting, you get a notification in your status bar at the top left of the SO page.
When the page is loaded, the browser makes a protocol upgrade request which looks like this:
Request URL:ws://sockets-se.or.stackexchange.com/
Request Method:GET
Status Code:101 Switching Protocols
Request Headersview source
Connection:Upgrade
Cookie:__qca=P0-1697817643-1763440830313; __utma=27376923.959753990.1338240830.1353943751.1384115154.33; __utmc=27693525; __utmz=27699983.1356175156.31.31.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided)
Host:sockets-se.or.stackexchange.com
Origin:http://stackoverflow.com
Sec-WebSocket-Extensions:x-webkit-deflate-frame
Sec-WebSocket-Key:6qFl45+6gZ526yMMo79zWQ==
Sec-WebSocket-Version:13
Upgrade:websocket
(Key3):00:00:00:00:00:00:00:00
Response Headersview source
Connection:Upgrade
Sec-WebSocket-Accept:B4h2G+gi78iNZZXg+o6iAztgF1I=
Upgrade:websocket
(Challenge Response):00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
The socket is then open, and the server can send updates to the browser. For example, a notification of my comment is received by the browser as:
{"action":"1-question-12993099","data":"{\"a\":\"comment-add\",\"id\":12993099,\"commentid\":19334206,\"acctid\":1298157}"}
It doesn't contain the actual comment; it appears that this is simply used to tell the browser to show the red icon. When you then click, it makes a request to get the page, including the comment. The question ID (12993099), comment ID (19334206) and account ID (1298157) is contained in that frame.
I cannot see anything in the above which would stop some hacker creating a web socket to listen to your notifications. The cookies look to me to be Google Analytics cookies to me, or at least the second and third ones do. Perhaps the first is some code which you wouldn't know, had I not just published it (no worries, I change it!).
In your example of Atmosphere, I know that when Web Sockets does not work, it defaults to long polling, which then requests a URL with the channel name in it. So you could get the client to generate a channel name which only it would know and associate that with the logged in user. But anyone sniffing the network would again have access to your traffic, so you'd have to secure it using secure web sockets (WSS) and HTTPS (for long polling fallback).

How to create one database connection per user on a Java Servlet application?

I am working on a website using Java Servlets and my research showed me that it is best to keep one database connection per user (rather than have only one connection sitting all the time on the background or connect to the database every time that a transaction needs to be made). I don't know how to accomplish this, however. What I am currently doing is in my Data Access Object class I have a
private static Connection conn;
and I have a HTTPSessionListener - on sessionCreated event I connect to the Database using this static "conn" variable, and on sessionDestroyed event I disconnect the "conn" variable:
...in my "MySessionListener"...
public void sessionCreated(HttpSessionEvent sessionEvent) {
System.out.println("Session created!");
DAO.connect();
}
public void sessionDestroyed(HttpSessionEvent sessionEvent)
{
System.out.println("Session destroyed");
String user = (String) sessionEvent.getSession().getAttribute("userid" );
if (user != null) DAO.signUserOut(user);
DAO.disconnect();
}
Now the problem with this is that:
I am afraid that this way I essentially degrade to only having one connection that everyone shares(instead of a connection per user as I wanted), just that I disconnect from time to time if there are no users. Correct?
If multiple users are online and one closes their session, they will close the connection for everyone until someone else starts a session and creates a new connection for everyone, correct? I cannot test this very well because I am testing it locally on my laptop, with 3 browsers, but even when I close a browser that had my website on, the session doesn't die immediately and I am not sure what exactly is going on. All i know is that sometimes I get an exception saying "No transactions allowed after connection is closed".
Typically this is achieved using connection pool. You can configure it to have specific number of connections available and the pool manages open and closing connections. Your code will only take available connection from the pool and return it when done.
See this (fairly generic) Wikipedia article.
Some well known pools are DBCP and C3P0.
There ate two issues here:
http session timeout
database session connectivity
You seem to be mixing the two session concepts.
HTTP session
You need to further familiarize yourself with client-server http mechanism. Closing the browser does not close the http session. When you close the browser, you have to code into your pages "on close". "On close"?? Absolutely not - there is no such thing as onclose in html/javascript. But there is onunload (as well as onload).
Why isn't there "onclose" in javascript/html? I think the people who invented http/html were paranoid over many contingencies. Perhaps, rightly so. Perhaps, we have to understand the mindset and motivation of html/http invention. So, you have no choice but concoct a chain-reaction of onunload events. ONUNLOAD/ONLOAD are html page events, not browser events. The whole html mechanism is page driven not browser driven. Therefore, when you close the browser, it would trigger onunload event for every tab on the browser.
You will have to make use of page onunload to inform the server that the user has intention to close the session. Otherwise, the server would have to depend on session timeout value to end the session. What if the user closes the browser on one of your pages on which you did not code in the onunload event? Too bad - that is why I wrote "concoct a chain reaction of onunload" on every page. Which is very tiresome and bothersome.
Sometimes. especially for highly mathematical servlets, the server takes a long time to respond. Then the client page would need an indication to differentiate between a server still processing a response vs the server has gone dead - session timeout enforced on the browser. e.g. http://support.microsoft.com/kb/813827 (How to change the default keep-alive time-out value in Internet Explorer).
May be, the server should poke at the browser page once a while to see if the browser session is still alive. Nope. Http is client pull technology. The server cannot push responses to the client. Why not? Why so silly? You have to read up on the whole http/html mindset/paranoia to understand. The browser can poke at the server but not vice versa.
Therefore AJAX and comet was invented/concocted. To simulate, to pretend on server push. With ajax you have some means for the server to psuedo-poke at the client. And that is what you have to do -- use ajax e.g. jquery or gwt. I prefer gwt.
What if the client computer had a power failure or the OS hit a blue screen, or the browser process was abruptly terminated? There would be no opportunity to trigger the onunload event for any of the pages.
Database connection session
Alex's answer hit the nail -- connection pooling. However, there are situations when I needed to have a database connection per session. Hmmm ... how do I do it? Yes, I store the connection as the session attribute. Therefore, there would be as many db connections as there are sessions. Which, essentially has the same effect as what you are currently doing.
Developing stateful web applications for a stateless(despite the cookies) and presumed unstable client requires cautiousness. What if the user presses the back button after logging out? The backed/prev page might contain an action that causes the server to use a db connection, which was already closed by the log-out page before the user pressed the back button. Or, it may be the server timed out due to client not having poked at the server for a duration longer than the session keep-alive timeout value.
Therefore, before developing a "multi-tier" client-server app, you have to sit down and chart out all your contingencies, with a good understanding of the mindset/paranoia of http technology. You need to infect yourself with http's compulsive obsessions in order to design your applications.

tracking Httpsession user session timeout

I am trying to monitor user session and alert user that the session is about to expire.
Anysolution either client side or server side will work for me , i just need to inform to the client that his session would be expired before session expires
Session timeout counter starts as soon as it gets idle. if there is a request from user [even if its ajax] then it won't time out. So you can maintain a counter on client side making sure that user is left idle for your webpage.
Update:
Add a Filter that will intercept each request and will update lastAccessedTime pass it to client in the form of some hidden parameter or cookies or something.. and use javascript to detect the timeout
Also See
detecting-idle-time-in-javascript-elegantly
The timeout should definitely be handled using a Javascript type of timer. Now, when you have a request on the server you should reset the timeout on client (the session timeout on the server will be automatically updated using the session tracking option of the server).
Now in another case that you perform actions on the client (but with no server interaction) then you should reset the timeout on the client using javascript, and use a dummy hidden internal frame posting some dummy form on a dummy page on the server. This would update the session timeout of the user on the server side.
You can also implement the last dummy thing functionality also with an ajax call on a dummy page. This might be a better solution.
Hope this helps you

What is called session store?

What is called session store in context of web applications/websites ?
Is it anything more than a temporary store of session variables?
Typically the user's first request to the site establishes a session. The session has a key which is passed to the user as a cookie, so that with every subsequent request the same session is retrieved.
The session store can store information about that user you don't want (or can't due to the length limit of cookies) to put in a cookie, for example the currently logged-in user ID or the contents of a shopping cart. This is usually in the form of some kind of serialized data structure depending upon the language/framework in use.
The reason why you might implement the session store in an external database rather than within the local web server would be to account for if you have multiple web servers in a pool; this way if the user's first request went to server A, and the next went to server B, your web app can still retrieve the same session data every time.

Session hijacking: Pros/Cons of a filter that suppresses Session IDs

I am trying to address session fixation/hijacking/sidejacking on an ATG/JBoss/Tomcat site. It seems that by far, the most commons recommendations are:
Grant a new session to the user when they log in. This prevents the attacker from being able to predict the session ID of the victim. I tried this approach first, but I fear it may not work in my case
Use a servlet filter to invalidate the session anytime a session ID (SID) is passed in the URL. The filter additionally prevents url rewriting for creating links w/ SIDs
What are the pros and cons of #2? Some that I've thought of:
Pros:
This seems like a broader protection than #1: #1 protects against malicious URLs being passed to the victim, #2 protects against any means of acquiring SIDs (insecure wireless networks, access to the machine, etc) - you can't just pass the SID you want to use a request parameter!
Cons:
Session management will be shot for users without cookies enabled.
Normal users will be logged out if they click a link w/ jsessionid specified, though I don't believe there will be any legitmate links like that in the system, due to the behavior of the filter.
2 is to stop Session Fixation.
You also need to take CSRF aka "Session Riding" into consideration. Here are methods of preventing CSRF.
Finaly don't forget the most overlooked OWASP, OWASP A9 - Insufficient Transport Layer Protection. This means that your Session ID must be transmitted over HTTPS at all times. If you don't then someone can use Firesheep to grab the account.
You could store a variable in the session that contains the user's IP, user agent, etc. or a hash of them and check it every request so that if it is hijacked the hijackers would have to fake those.
Not perfect but it helps.

Categories

Resources