getThreadLocalRequest().getSession(false) always null - java

i have some problems trying code login+cookies .. when the user is login i create the session
getThreadLocalRequest().getSession(true)
and when i want to check if session its still alive always return null
HttpSession session = getThreadLocalRequest().getSession(false);
if (session != null) {
}
When i check the HttpRequest (when i check session alive) this have
Cookie: JSESSIONID=a1042a8e-9ebc-45b8-a3d8-12161885be96
and the cookie is ok.
I use Eclipse+Development mode
Server side code :
public String login(String rut, String pass) throws AuthenticationException {
//if UserPassMatch ...
session = this.getThreadLocalRequest().getSession(true);
//set user bean
session.setAttribute("beanSession", us);
HttpServletResponse response = getThreadLocalResponse();
Cookie usernameCookie = new Cookie("JSESSIONID", us.getSessionID());
usernameCookie.setPath("/");
usernameCookie.setMaxAge(60 * 60 ); //1 hora
response.addCookie(usernameCookie);
}
#Override
public String checkIfSessionStillActive(String token) {
HttpServletRequest request = getThreadLocalRequest();
//Here ALWAYS return null
HttpSession session = request.getSession(false);
if (session != null) {
//check sessionId and search User Bean
}
return token;
}
From client side nothing special just call checkIfSessionStillActive for check if session exists and go throw the token or go to login if it's not. When the user is logged in still return session NULL. I use MVP pattern and i call from AppController and i use the same rpcService. At once the user login i check session and its exists, but if i call checkIfSessionStillActive this not found any session.
Really i read a lot of code and what i found its almost the same thing, ¿can any help me?

Are you using a subclass extending RemoteServiceServlet and calling on a object created somewhere else (for example in spring context) and have extended RemoteServiceServlet? If yes following will solve your problem
For each request a new instance of RemoteServiceServlet is created. Problem is that the thread local variables defined in super class of RemoteServiceServlet are not static, hence for each object you have different variable. When ever you process call in above scenario, your request response thread local variables are initialized for the object which receives but it does not sets thing for object on which you are invoking a method.
I used a workaround by creating a Class with static threadlocal varrible and set values before invoking on second object. Now swcond object can also access them.

Have you tried using setMaxInactiveInterval() rather than messing with the cookie directly?

Related

Session destroyed after redirection

I'm facing an issue in a new application I'm working on it.
I made a new entry point (used for a non logged user) and I want to store a value in the user session (value comes from a path param).
So, my entry point like this :
#GET
#Path(MYPATH + "/{" + VALUE + "}")
public Response myEntryPoint(#PathParam(VALUE) String value, #Context HttpServletRequest httpServletRequest, #Context HttpServletResponse response) {
httpServletRequest.getSession().setAttribute(URL, value);
LOGGER.info(HttpServletRequest.getSession().getId());
return Response.seeOther(new URI(the login system)).build();
}
The "login system" is another application and will perform some actions like the login of the user and then call another endpoint of my application.
My goal is to retrieve the value put on the session.
So, I wrote the following code :
#GET
#Path(action)
public Response action(#Context HttpServletRequest request) {
LOGGER.info(request.getSession().getId());
String value = (String) request.getSession().getAttribute(URL);
}
I would expected the value contained the value given on parameter on the myEntryPoint call.
But, as you can imagine, the String value is empty and if I check the session ids of the requests (myEntryPoint & action) are differents.
When the action method is called, a lot of filter chained are called.
Do you know what I did wrong?
I tried the same exercice with cookies in place of session, but without success.
Value is still empty.
Do you have any idea / suggestion?
Thanks in advance

Trying to retrieve HttpSession object

For some background, I'm using JBoss AS 7 with EJB. I'm sending a message to my server from the client using errai message bus when it initially connects to retrieve its session ID so that I can make requests from it later on and have the server respond to the specific client.
How do I go about doing this? Can I inject a HttpSession object server side somehow? I'm very new to this so please bear with me. If I'm too vague let me know and I'll try to elaborate more.
If you are sending a message to an ErraiBus service method, you will have the Message object available. You can retrieve the session from it and get that session's ID like this:
#Service
public class ClientHelloService implements MessageCallback {
#Override
public void callback(final Message message) {
HttpSession session = message.getResource(
HttpServletRequest.class, HttpServletRequest.class.getName()).getSession();
System.out.println("Client said hello. Session ID: " + session.getId());
}
}
If you are instead sending the message to an Errai RPC endpoint, you will not have such easy access to the message. In this case, you will have to use the RpcContext.getSession() method:
#Service
public class ClientHelloRpcServiceImpl implements ClientHelloRpcService {
#Override
public void hello() {
HttpSession session = RpcContext.getHttpSession();
System.out.println("Client said hello. Session ID: " + session.getId());
}
}
The way this works is simple but ugly: RpcContext class stores the Message object that contained the RPC request in a ThreadLocal, and it just retrieves the HttpSession from that.
// the following variable is in the Http servlet service() method arguments
// only shown here this way to demonstrate the process
javax.servlet.http.HttpServletRequest serviceRequest;
javax.servlet.http.HttpServletResponse serviceResp; // addCookie()
javax.servlet.http.HttpSession cecil;
javax.servlet.http.Cookie[] reqCk;
// "(boolean overload) "true" creates the session" or call the other overload version method with no argument
// to retrieve the session getSession() "the server container stores and creates sessions"
// false in that version is to avoid bothering for a session to cut down uneeded processing
cecil = serviceRequest.getSession();//creates a session if it does not have one
String httpSession_ID = cecil.getID();
if((reqCk = serviceRequest.getCookies()) == null){
// perhaps create a cookie here using "new class "
// cookiePiece = new javax.servlet.http.Cookie("COOKIENAME",....); ....YOU MUST LEARN THE COOKIE PARTS WRITING RULES FOR BROWSER COOKIES !!! ; ; ;
serviceResp.addCookie(cookiePiece); // now is on the servers array "reqCk"
}else{
// process the cookie here using javax.servlet.http.Cookie methods
}
Other ways of storing and retrieving data are session scoped JSP or JSF beans.

How to run a thread from struts2

i am developing a sturts2 webapplication, i am having a login page with username and password fields. As soon as user submitted form with values , i am validaing the login, if the user provides valid username and passoword, it is redirected to home page. While redirecting the home page, i have to call a thread in which i sets some data in session for future use. How to do this ?
What i did is
import com.opensymphony.xwork2.ActionContext;
if( loginSuccess(userInfo) ) {
initializeDatas(); // calling thread after userInfo bean validated
// redirecting to home page
return HOME_PAGE;
}
I have added a new class which implements runnable.
class intilalizer implements Runnable {
#Override
public void run() {
try {
System.out.println("Started to set values ");
List<String> iphoneSdks = new ArrayList<String>();
List<String> iphoneOSSdks = IosSdkUtil.getMacSdks(MacSdkType.iphoneos);
List<String> simSdks = IosSdkUtil.getMacSdks(MacSdkType.iphonesimulator);
List<String> macSdks = IosSdkUtil.getMacSdks(MacSdkType.macosx);
iphoneSdks.addAll(iphoneOSSdks);
iphoneSdks.addAll(simSdks);
iphoneSdks.addAll(macSdks);
ActionContext context = ActionContext.getContext();
System.out.println("context ===> " + context); // here i am getting null value
String httpRequest = ServletActionContext.HTTP_REQUEST;
System.out.println("httpRequest =====> " + httpRequest);
Object object = context.get(httpRequest);
System.out.println(object);
HttpServletRequest req = (HttpServletRequest) object;
req.setAttribute(REQ_IPHONE_SDKS, iphoneSdks);
req.setAttribute(REQ_IPHONE_SIMULATOR_SDKS, simSdks);
System.out.println("Value initialized####");
} catch (Exception e) {
e.printStackTrace();
}
}
}
I am getting
java.lang.NullPointerException
at com.photon.phresco.framework.actions.intilalizer.run(Login.java:286)
at java.lang.Thread.run(Thread.java:680)
I am getting this error on line .
ActionContext context = ActionContext.getContext();
System.out.println("context ===> " + context); // here i am getting null value
From Struts 2 JavaDoc
The ActionContext is thread local which means that values stored in the ActionContext are unique per thread
You just create a new Thread so your ThreadLocal variables are not available there. You should do something like this:
import com.opensymphony.xwork2.ActionContext;
if( loginSuccess(userInfo) ) {
ActionContext context = ActionContext.getContext();
initializeDatas(context); // calling thread after userInfo bean validated
// redirecting to home page
return HOME_PAGE;
}
The best way will be pass context to Thread constructor. But I am not sure that COntext is ThreadSafe.
I'm just wondering WHY do you need to start a new Thread to put some data in session
(thing that you say you wanna do, but that you actually don't do in the posted code, where you instead put stuff in request).
You can simply implement SessionAware Interface from your Action(s).
Actions that want access to the user's HTTP session attributes should
implement this interface.
This will give them access to a Map where they can put objects that
can be made available to subsequent requests.
Typical uses may be cached user data such as name, or a shopping cart.
It is not mandatory, but it is a best practice for accessing session from within the Actions, instead of asking to ActionContext:
You can obtain the session attributes by asking the ActionContext or
implementing SessionAware. Implementing SessionAware is preferred.
If needed, here is a little example of usage: http://www.splinter.com.au/how-to-use-sessions-with-struts-2/
if( loginSuccess(userInfo) ) {
// redirecting to home page
return HOME_PAGE;
initializeDatas(); // calling thread after userInfo bean validated
}
That won't work. The method will end after the return call. Try calling the method that creates the new thread first.
if( loginSuccess(userInfo) ) {
// redirecting to home page
initializeDatas(); // calling thread after userInfo bean validated
return HOME_PAGE;
}

Using a filter to add a cookie to the users session

Update: The issue is with the setting used for the MaxAge. Setting it to zero will cause the cookie to be deleted, hence it was shown in the response header but was then deleted and did not show in the request. Setting it to -1 so that it will not be stored persistently
I am doing some work on a filter in which I want it to set a cookie to indicate that the user qualifies to take a survey and that the next time he comes back to the site a survey popup window will be displayed.
I am not seeing any errors in the logs but the cookie never gets set.
Can a filter be used this way to add a cookie? Is there where a HttpServletResponseWrapper comes into play?
The thought here is that when the user comes to the the site there is a check to see if the cookie is present. If it is not then a cookie is created and added to the response. As the user navigates the site, the cookie check method is called to make sure that the hit counter is not increased for that given user.
The cookie check method never sees the cookie. Using web developer plugin for firefox, the cookie in question is not present.
Below is the filter class with the relevant methods.
public class HitCounterFilter extends TemplateFilter {
public void doMainProcessing(ServletRequest pRequest, ServletResponse pResponse, FilterChain pChain) {
HttpServletRequest httpRequest = (HttpServletRequest) pRequest;
HttpServletResponse httpResponse = (HttpServletResponse) pResponse;
// prevent thread interference and memory consistency errors
synchronized (lock) {
int hitCounter = this.readFile(localFile);
// if user has not been counted
if (!this.checkForCookie(httpRequest, "gtgo_visitor")) {
this.writeFile(localFile, ++hitCounter);
this.createCookie(httpRequest, httpResponse, String.valueOf(hitCounter), "gtgo_visitor");
}
}
}
private void createCookie(HttpServletRequest pHttpRequest, HttpServletResponse pHttpResponse, String pCookieValue, String pCookieName) {
try {
Cookie cookie = new Cookie(pCookieName, pCookieValue);
URL url = new URL(pHttpRequest.getRequestURL().toString());
cookie.setDomain(url.getHost());
cookie.setPath(this.getCookiePath(pHttpRequest));
cookie.setComment("user is not eligible to take the survey this time");
cookie.setMaxAge(0);
pHttpResponse.addCookie(cookie);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
private boolean checkForCookie(HttpServletRequest pHttpRequest, String pCookieName) {
for (Cookie cookie : pHttpRequest.getCookies()) {
if (StringUtils.equalsIgnoreCase(cookie.getName(), pCookieName)) {
return true;
}
}
return false;
}
}
The issue is with the setting used for the MaxAge. Setting it to zero will cause the cookie to be deleted, hence it was shown in the response header but was then deleted and did not show in the request. Setting it to -1 so that it will not be stored persistently - it will be present as long as the session is active (removed once the session is closed)
I haven't worked with the SCAM project before, but it looks like that is what you're using. I'm not sure if the super class's implementation of doFilter calls your implementation's doMainProcessing method before calling the FilterChain's doFilter method or not.
Because the framework passes the FilterChain into your doMainProcessing method, it is likely that it expects that your implementation will call pChain.doFilter(pRequest, pResponse, pChain).
I might be wrong about this, but if the filter chain is abandoned, its possible that the headers written to the ServletResponse object, which include the cookie you have attached, will not be returned to the client.
In any case, unless you are specifically blocking access to the requested resource, its wise to propagate the request using the FilterChain.

How do I use autologin in liferay?

I want to login my users automatically from our application. I know liferay has an auto login feature, but I don't know how to use it. I didn't find much valuable information on the web.
What do I need to do to make autologin work?
I want to login a user automaticaly when he clicks a link, without him having to enter name and password. The name and password is saved on our application database.
I believe the OP has no use for an answer now. Nonetheless, this deserves a comprehensive answer. In fact, I am surprised that it does not have one yet.
First of all, this is a bad idea: such an arrangement as the one proposed by the OP is really too insecure. Nevertheless, a solution to the described problem can be a good prototype for someone creating an autologin for Liferay.
Now, let us say you want to automatically log in any user whose screen name is sent in a query string parameter. For example, if one access http://localhost:8080/web/guest/home?insecurely_login_user=juju then the Liferay in the juju user should be logged in. How to do that? Follow the steps below:
Create the autologin class
Firstly, create a hook plugin. In its docroot/WEB-INF/src directory, creates a class implementing the com.liferay.portal.security.auth.AutoLogin interface. In my example, I will call it br.brandizzi.adam.liferay.insecure.InsecureAutoLogin.
The AutoLogin interface has only one method, called login(), which expects two parameters (an HttpServletRequest and an HttpServletResponse instances) and returns an array of strings. So, my class will look like this without implementation:
public class InsecureAutoLogin implements AutoLogin {
#Override
public String[] login(HttpServletRequest request,
HttpServletResponse response) throws AutoLoginException {
// TODO Auto-generated method stub
return null;
}
}
The AutoLogin.login() method will try to retrieve the information necessary to the authentication from many sources, mainly the request object. If it decides that the user should be logged in, it returns an array with relevant data for authentication; if it decides to not log the user in, it can just return null.
In our case, we try to get the name of the user from the the insecurely_login_user parameter from the request. If there is such parameter, we will proceed with the login; if there is no such parameter, it just returns null:
String screenName = request.getParameter("insecurely_login_user");
if (screenName == null || screenName.isEmpty()) {
return null;
}
So we have the screen name. What to do now? Let us get a user from the database with the same screen name.
long companyId = PortalUtil.getCompanyId(request);
User user = UserLocalServiceUtil.getUserByScreenName(companyId,
screenName);
If a user wich such a screen name exists, it will be retrieved and attributed to the user variable. In this case, the authentication should be successful and the autologin class should return an array of three strings - the credentials. Those are the values to be returned as credentials, in the order they should appear in the array:
the user id as a string
the password of the user, which can be encrypted or not;
a boolean value, cast to string, indicating if the password is encrypted.
So here is the line:
return new String[] {
String.valueOf(user.getUserId()),
user.getPassword(),
String.valueOf(user.isPasswordEncrypted())
};
If a user is not found, however, an exception will be thrown. So, we have to surround the code above with a try/catch construction. If an exception is thrown, just return null:
try {
long companyId = PortalUtil.getCompanyId(request);
User user = UserLocalServiceUtil.getUserByScreenName(companyId,
screenName);
return new String[] { String.valueOf(user.getUserId()),
user.getPassword(),
String.valueOf(user.isPasswordEncrypted()) };
} catch (Exception e) {
return null;
}
In the end, this is my InsecureAutoLogin class:
public class InsecureAutoLogin implements AutoLogin {
public String[] login(HttpServletRequest request,
HttpServletResponse response) throws AutoLoginException {
String screenName = request.getParameter("insecurely_login_user");
if (screenName == null || screenName.isEmpty())
return null;
try {
long companyId = PortalUtil.getCompanyId(request);
User user = UserLocalServiceUtil.getUserByScreenName(companyId,
screenName);
return new String[] { String.valueOf(user.getUserId()),
user.getPassword(),
String.valueOf(user.isPasswordEncrypted()) };
} catch (Exception e) {
return null;
}
}
}
Registering the autologin class
Now our hook should register this class as an autologin processor. That is really easy.
First, edit the file docroot/WEB-INF/liferay-hook.xml adding a portal-properties element with the value portal.properties:
<?xml version="1.0"?>
<!DOCTYPE hook PUBLIC "-//Liferay//DTD Hook 6.1.0//EN" "http://www.liferay.com/dtd/liferay-hook_6_1_0.dtd">
<hook>
<portal-properties>portal.properties</portal-properties>
</hook>
Now, create a file named portal.properties at docroot/WEB-INF/src. It should contain a property named auto.login.hooks whose value should be the name of our class:
auto.login.hooks=br.brandizzi.adam.liferay.insecure.InsecureAutoLogin
And that is it. Deploy this hook and your autologin will work.
Conclusion
As I have said, you should not use such an unsafe "authentication" method. It is too easy to bypass it, getting even administration permissions! However, if you follow these steps, you have a skeleton to create a better autologin feature. Also, I know some people really want to do something like this insecure "authentication" method and sometimes we have to suspend our judgments and just help one to shoot one's feet...
The source code of this project can be found here and you can download the WAR here.
Step 1: Create a class CustomLoginFilter and implements from AutoLogin interface.Override login method. Code as follows.
public String[] login(HttpServletRequest req, HttpServletResponse response)throws AutoLoginException {
//Get the login parameter
String loginEmailId = ParamUtil.getString(req, “_58_login”);
String password = req.getParameter(“_58_password”);
String[] credentials = new String[3];
credentials[0] = userId
credentials[1] = loginEmailId;
credentials[2] = password;
//Write your business logic Here and return String[].
}
Step 2: Write below code in portal-ext.properties
// you get full control from this custom class.
auto.login.hooks=com.bolog.portal.login.security.CustomLoginFilter
//Override Liferay Authentication pipeline
auth.pipeline.enable.liferay.check=false
auth.pipeline.pre=com.bolog.portal.login.security.CustomLoginAuthenticator
Step 3: Create class CustomLoginAuthenticator and implements from Authenticator.
Override authentication methods.
public int authenticateByEmailAddress(long arg0, String arg1, String arg2,
Map<String, String[]> arg3, Map<String, String[]> arg4)
throws AuthException {
//Write Your business login here and if authentication success then return 1 otherwise return 0;
return 0;
}
public int authenticateByScreenName(long arg0, String arg1, String arg2,
Map<String, String[]> arg3, Map<String, String[]> arg4)
throws AuthException {
//Write Your business login here and if authentication success then return 1 otherwise return 0;
return 0;
}
public int authenticateByUserId(long arg0, long arg1, String arg2,
Map<String, String[]> arg3, Map<String, String[]> arg4)
throws AuthException {
//Write Your business login here and if authentication success then return 1 otherwise return 0;
return 0;
}
Step 4: If authentication fail then you can also redirect any page by following code
if(Validator.isNull(credentials) || credentials[0]==null){
req.setAttribute(AutoLogin.AUTO_LOGIN_REDIRECT, “Your Login page path”);
}
What exactly do you mean by "autologin"? If you want Liferay to check wheter the user is already authenticated by some external entity (like a single sign-on server as CAS), you can just enable that in the portal.properties. There it's already preconfigured for the liferay supported authentication mechanisms. Otherwise you might need to implement your own autologin hook (as indicated in this post for example
Well found it.
Step 1: Click on add iframe and let the configuration view pop up.
Step 2: Provide the url and if there are any variables like (www.mysite.com/Action=Login&User . . . .), add the Action=Login in hidden variables text field.
Step 3: Click authenticate and select form based authentication. In this, make usre that the user field name and password field name are given correctly, and the values will be '#screen_name#','#password#'.
For example, suppose the url is something like www.mysite.com/Action=Login?User=aj&Password=aj.
User Name (field)=User
Password (field)=Password
User Name (Value)=aj
Password (Value)=aj
Hidden variables(field)=Action=Login
Now, whenever any user logs into the liferay applicaiton, if his/her account exists in the site specified(in the url), it will log into that site automatically(acts like a single sign on).
This is working !!!
-Aj

Categories