Spring + GWT project - execute handler on every user action - java

I'm new one in Spring, GWT and even Java World. So be patient. We have relatively big project, which one used Spring, GWT, Hibernate and Signal-Com Inter-Pro (Russian solution for html form signing to secure identified clients).
So now when user tried to log in into system, it read certificate s/n from http headers, compare with s/n from database. If they are equal, user can work with system. Otherwise, notify user and security administrator.
My current task is to add this check to every user action, i.e. GWT button click, switching to next view and so on. Is there a place where you can organize such a test?
TECH INFO:
Login form have redirect to special page
final FormPanel form = new FormPanel();
form.setAction(GWT.getModuleBaseURL() + "checkCertificate.htm");
Next, checkCertificate.htm have mapping in dispatcher-servlet.xml:
bean name="/base_dir/checkCertificate.htm" class="...CheckCertificateController">
property name="checkSignature" ref="checkSignature"/>
/bean
All necessary certificate actions are implemented in
public class CheckCertificateController extends AbstractController {
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
...
}
which is called when user click login button.

We have a Servlet Filter which performs a security check each time the user needs any information from the database.
Although that's not quite the same as performing a check with each user action, it works pretty effectively for us.
Alternatively you could set up a regular repeating command which would check at specific intervals and lock the user out if their serial number was invalid.

Related

Implementing Collaborative Authentication in Java Web Application

I've a requirement to build a Java based web application where a resource should be available only when all the authorized users of that resource are logged in. Also, if any authorized user logs out, the resource should no longer be available to any of them.
The resource could be of any type(html pages, pdf documents, spread sheets etc.,)
Is there any existing authentication standards/protocols that supports this type of requirement or I've to build this from scratch?
the resource should be available only when all the authorized users of that resource are logged in. Also, if any authorized user logs out, the resource should no longer be available to any of them.
Once you have given access to the resource to an user, this user will be able to download / take screenshots / save / record the resource, no matter if it's a PDF document, an image, an audio file. I don't know the context and the goal of what you're trying to build, but you should know that it will be insecure in any case.
Even putting this consideration aside, you'll need a real-time solution. Once the user has loaded the page containing the resource, you need to be able to hide or deny modification rights to him. This means you have to use something like WebSockets or Ajax Polling on the client side to have the frontend know when your server considers that not all the required users are online, and that the access to the resource should be "denied". But once more since this is client-side code it can easily be changed or altered, the requests it is sending can easily be blocked by the user, so it is once again inherently insecure.
I'd suggest giving a little bit of context here and describing what is the problem you're trying to solve, because most likely there's a more reasonable solution to solve it.
If what you need to do is to deny modification rights if not all the "resource owners" are online, it is more easily doable since the modifications will happen on the server side. In this case, a solution using WebSockets could quite easily be implemented but I don't know a library or framework that does such a thing. Most likely you will have to build it yourself.
If you're not constrained to use a specific web framework, feel free to try the following filter based implementation for jersey. Note that you still need to add a fair amount of custom code for handling the logic of "Collective authentication" as jersey only provides the basic tools required for this, and it doesn't explicitly implement the whole concept. Here's how you could do it, on a high level:
class AuthorizationProvider {
public void authenticate(ContainerRequestContext requestContext) {
// Here you would need to query your database to get the Collection of Users belonging
// to the "Collective" Role. You would then check if they are all logged in.
// A really abstract version would look like this, assuming you've already queried the DB
// and have a reference to the above mentioned Collection.
if (collectiveUsers.size == collectiveUsers.stream().filter(User::isLoggedIn).count()) {
return true;
}
return false;
}
}
class AuthorizationRequestFilter implements ContainerRequestFilter {
private final AuthorizationProvider authorizationProvider;
#Override
public void filter(ContainerRequestContext requestContext) {
if (authorizationProvider.authenticate(requestContext)) {
// serve whatever it is you want to serve if all required users are logged in
} else {
// otherwise reject the request
requestContext.abortWith(Response
.status(Response.Status.UNAUTHORIZED)
.entity("Resource available only after collective login")
.build());
}
}
}
#ApplicationPath("/")
class MyApplication extends ResourceConfig {
public MyApplication() {
// Register the filter
register(AuthorizationRequestFilter.class);
}
}
Apart from this, you would also need to handle the Login part.
You would assign these specific users the Collective role, and you would mark them as logged in, whenever they successfully pass through login authentication.
If all the above conditions are met, you should be able to successfully serve your "Collective only" page, only when all "Collective" users are logged in.
This also covers the part where if either one of these users logs out, you store the state in your database (mark the Collective user with isLoggedIn = false). So from this point on, whenever somebody requests the page, it will return Unauthorized.
Conversely, you can also attempt to implement SSE (Server sent events) to actively update the frontend part, if somebody logs out. With this, the page will actively be disabled even if somebody has already managed to get it previously.
Container request filter source and example, for reference, jersey docs

How ensure authentication with AJAX functions? Currently using Java Bean for authentication

I have a web app that uses a Java Bean for login functions right now and all of the JSP pages check the Bean to make sure the user is logged in. I am also introducing some AJAX functionality now with servlets and I see that of course those exchanges don't check authentication. I'm wondering how I should handle this. For example, I don't want someone to be able to logout, hit back button, then submit something with the AJAX functions successfully.
I can't access the bean from the servlet to check the login (totally wrong context and static vs non-static). I guess I could set a flag with the user entry in the database table denoting logged in or not. Then I can detect timeout logoffs and update the flag as well. But that way would require extra database accesses every time something is done. It would duplicate functionality in some way, but I guess I could perhaps use that just for the AJAX stuff. One difference with that would be the user would not be able to be logged in on multiple places at once as currently.
How is this kind of thing normally done?
Thanks for any help!
You could use session to store that flag instead of the database, and when the user logs out you should remove that flag and destroy the session. In login method
HttpSession session = req.getSession(true);
session.setAttribute("loggedIn",true)
And in your AJAX code
if(eq.getSession(true).getAttribute("loggedIn")==true)
doWork();
else
error("not logged in");
The webcontainer will handle timeouts for you, keep track of each user and his session, and so on.
But I would recommend that you use a standard for managing authntication

Setting UserPrincipal in form based authentication

[JEE, MVC-JSP+Servlets, TomEE]
Using form based declarative authentication (container managed). Is it possible to explicitly set UserPrincipal? (to log some user in).
I know I can check whether there is logged in user or not with request.getUserPrincipal()!=null.
Actually I am facing following situation: I have a register.jsp that is being used for new users registration. So data from this jsp are sent to servlet where new user object is created and persisted to database. So, now when user has registered, he/she should be automatically logged in. So, I was thinking how can I implement this automatic login after registration.
If you are on Servlet 3.0 and above, use HttpServletRequest.login().

Passing variables to a POST request from an outside controller

Since you guys have been very helpful in my early steps into the Play Framework (thanks for that), here it goes again:
We have a working registration controller, that POSTS all credentials to the database.
But then, we want to make it possible to be immeadiately logged in afterwards. Below is the code that makes this work:
public static void doRegistration(#Valid User user) {
//registering the user
try{
SecureController.authenticate(user.username, user.password, false, "MainController.index");
}catch(Throwable ex){
MainController.index();
}
This works fine, but it is not very safe because it GETs all the credentials to the server. I know I have to edit my routes file somehow, but I can't see how.
The routes file:
* /account SecureController.login
POST /account/register RegistrationController.doRegistration
GET /account/register SecureController.login
Somewhere should be the action SecureController.authenticate, but what do I have to put in the column after the POST... It can't be /account/register, because that fails...
Thank you beforehand!
I am not sure I understand your issue. The routes file is just a way to configure your URLs to be pretty URLs. If you don't specify them, then it falls back on default {controller}/{method} syntax.
The issue you are having, is that when you call another controller Play performs a redirect to that controller's method, which involves sending a request back to your browser telling it to redirect (this ensures that the state of the application is reflected in the URL within the browser). A redirect needs therefore to send a GET request, and included in the GET request will be your parameters.
what you are trying to do, as you said, is not safe. What you should do (not the only option, only one possibility) is:
Maintain your current doRegistration action for the user
Create a service class (that does not inherit Controller). It can be static or require instantiation (with static methods should be enough though).
Add a #Before method to a common controller that will be executed always. One way is to create a controller with a #Before method and add this controller to all other controllers via the #With annotation, so that #Before will be executed always for all controllers. It requires you to add a #With to each new controller, but I believe it keeps the code quite clean.
The idea would be that the controller calls the authenticate method from the service class. It's a simple static This method checks the user (if it's enabled, has proper license, whatever) and sets some parameters in the session (via Session object).
To help with this you may want to create another authenticate method in the user that returns the attributes to set (for example in a Map, if it contains an "error" key the user can't be authenticated for some reason). How to do this step can change according to your requirements.
Once the Session has been set, you redirect to the page of your election (main, profile, etc). As you have the common #Before method, this will be executed. This method should verify the credentials in the session (user authenticated, license type, etc) and act accordingly. You have an example in the Secure controller of Play, but you could create your own.
With this, you could user the authenticate method of the service from any controller, allowing authentication via multiple methods, and using a common point to verify the session.

Java EE Authentication Error Handling

We are currently trying to implement a web application which is using the Java EE authentication mechanism with a FORM-based login, inside the Websphere 6.1 web container. If the authentication is successful, we have everything working; the LDAP membership groups are being retrieved, the group to role mapping is being performed, and the roles are being returned to and correctly interpreted by the web application.
If the authentication is not successful, the form-login-error page is being returned. However, this is a static page that simply says something like "there was an error". How do we trap the specific error that prevented the successful login (username/password incorrect, LDAP repository unavailable, account locked, password expired, etc.)? It seems like there should be some easy way to do this, as you would want to treat some "security" exceptions differently than others.
I use Struts so it will do forwarding for you. If you don't have a framework (why not?) you'll will have to do it manually.
The Java EE spec covers the j_security_check servlet.
The login page POSTs j_username and j_password to the j_security_check servlet. Your app will be configured to error to an unauthorized page (see web.xml) but will (initially) call a servlet. 401 or 403 will go to a forbidden page (again web.xml)
Inside that servlet (which extends the HttpServlet) - you will check for all that good stuff.
public final void doGet(javax.servlet.http.HttpServletRequest request,
javax.servlet.http.HttpServletResponse response)
throws javax.servlet.ServletException, java.io.IOException
{
// initialize the app
AppInit initializer = new AppInit();
// get the logger
log = new Log4jWrapper(this.getClass());
// initialize the application session
HttpSession sess = request.getSession(true);
sess.setAttribute(CommonConstants.SESSION_CURR_USER_ID, request.getRemoteUser());
// initialize the JSP to forward to based on the user role
String fwdJSP = "SetupMainPage.jsp";
if (request.isUserInRole(CommonConstants.ROLE_MANAGER)) {
log.debug("User is a Manager");
}
//else other role checks - (these are users in groups in the LDAP)
// initialize the application session and set a variable to indicate that
// we are coming from a first time login (not a timeout login)
sess.setAttribute(CommonConstants.SESSION_COMING_FROM_INITIAL_LOGIN,"TRUE");
disp = getServletContext().getRequestDispatcher("SetupMainPage.jsp");
disp.forward(request, response);
}
//else failure
Unknown user
[11/22/08 8:54:47:993 EST] 7f6ac69c FormLoginServ E SECJ0118E: Authentication error during authentication for user s
right user - wrong password, but the request.getRemoteUser() will have a value
[11/22/08 8:56:45:082 EST] 7f51469c FormLoginServ E SECJ0118E: Authentication error during authentication for user jbsymolo
Unfortunately - i don't have any examples of someone locked out but I going to assume that the main security directory (LDAP) you will have an entry for the user for that.
This is from someone else (so I can't take credit)
I think this page describes how to do what you want to do.
Specifically how to retrieve the authentication exception from an arbitrary underlying authentication source (looks like Websphere calls them user registries).
Throwable t = com.ibm.websphere.security.auth.WSSubject.getRootLoginException();
if (t != null)
t = determineCause(t);
Where determineCause() is defined on the same page. This way, even if your server is configured to authenticate against a John Deer tractor, you will have access to the "OutOfGasLoginException" if there is one. The above code can go into the Servlet, Servlet Filter, or JSP that is redirect to by the container (as described above by jsymolon). It simply examines the exceptions and then places a corresponding friendly error message on the resulting page.
This is ancient knowledge - I believe to have done such a thing with tomcat. There was, as far as I can remember, no standard way, as the implementation was completely decoupled from the request and frontend web stuff, so that it was difficult to establish any means of communication between the authenticating component and the frontend (e.g. error page).
We ended up with a tomcat specific way, relying heavily on the current implementation. I'm no longer with that company, so I can't tell about the current state of the code or the solution we chose back then. I believe you'll also have to have some Websphere specific solution - be it the use of thread local variables, keying messages with the username that attempted to log in, somehow getting hold of the session identifier or similar.
Check this article Securing J2EE Applications with a Servlet Filter. I believe it covers your requirement to be able to pass the reason for the authentication error.
The JavaEE specification does not provide a standard mean to get an authentication feedback like error codes.
According to the following IBM Redpaper about z/OS security integration in gray note on page 57: IBM specific extension is available so that the error page JSP can report a specific message (like password expired) based on an error status code.
According to the WebSphere InfoCenter the FormLoginWeb sample from the TechSamp package in your WebSphere installation (samples/src/TechSamp/FormLoginWeb) is supposed to demonstrate such IBM specific extension but... The only thing interesting is the LoginFilter that intercepts calls on /j_security_check and is able to do pre-login validation and post-login action as explained in details in that paper.
With such a mechanism it is possible to get login exception from JAAS Subject and set an login error code in HttpSession so that the error page can generate a specific message.

Categories