Struts2 login action class seems to be reused

classic Classic list List threaded Threaded
35 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Struts2 login action class seems to be reused

Prasanth-2
Hi,

I have an application which uses both struts1 & struts2. The login action was recently moved to struts2. Immediately after the deployment we were notified that one user is seeing a different user
information, so we had to move to older war files. I am not able to replicate it. But after investigating the logs it seems like couple users were logged in as soon as they requested the login page.
For the database entry to happen it has to verify the username and password in the action class, but the fact that there is no POST entry at that time from that IP in my access log makes me believe
that the action class some how already had that information from a prior user.

I do have a login filter to check if users are logged in when accessing other pages. In this filter I have the below two lines, we had to do this as we will have requests forwarded from one
application to another and when that happens we are getting class cast exception for ActionMapping class and valueStack. Not sure if the behavior is a side effect of having the below lines.

            request.setAttribute("struts.actionMapping", new ActionMapping());       
            request.setAttribute("struts.valueStack", null);

We are using Struts 2.3.34 and Wildfly.

Appreciate any insights you might have.

Thanks,
Prasanth

Reply | Threaded
Open this post in threaded view
|

Re: Struts2 login action class seems to be reused

Prasanth Pasala
I was able to replicate the issue today. Asked few users to keep logging in and ran jmeter to access login page, with out putting any username or password. Out of the 100 attempts 2 attempts were
successful in getting in with out username/password. I am seeing database login entries for these two. Which would happen only if a valid session is not present and user has provided username/password.

Thanks,
Prasanth

On 03/01/2018 02:27 PM, Prasanth wrote:

> Hi,
>
> I have an application which uses both struts1 & struts2. The login action was recently moved to struts2. Immediately after the deployment we were notified that one user is seeing a different user
> information, so we had to move to older war files. I am not able to replicate it. But after investigating the logs it seems like couple users were logged in as soon as they requested the login page.
> For the database entry to happen it has to verify the username and password in the action class, but the fact that there is no POST entry at that time from that IP in my access log makes me believe
> that the action class some how already had that information from a prior user.
>
> I do have a login filter to check if users are logged in when accessing other pages. In this filter I have the below two lines, we had to do this as we will have requests forwarded from one
> application to another and when that happens we are getting class cast exception for ActionMapping class and valueStack. Not sure if the behavior is a side effect of having the below lines.
>
>             request.setAttribute("struts.actionMapping", new ActionMapping());       
>             request.setAttribute("struts.valueStack", null);
>
> We are using Struts 2.3.34 and Wildfly.
>
> Appreciate any insights you might have.
>
> Thanks,
> Prasanth
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Struts2 login action class seems to be reused

Yasser Zamani-2


On 3/3/2018 12:37 AM, Prasanth Pasala wrote:
> I was able to replicate the issue today. Asked few users to keep logging in and ran jmeter to access login page, with out putting any username or password. Out of the 100 attempts 2 attempts were
> successful in getting in with out username/password. I am seeing database login entries for these two. Which would happen only if a valid session is not present and user has provided username/password.

Shouldn't login page being accessible always? How do you try access
login page, calling directly to jsp? Or action? How do you authenticate
that access try, via session values? Via request parameters and querying
database?

> Not sure if the behavior is a side effect of having the below lines.
>
>             request.setAttribute("struts.actionMapping", new ActionMapping());      
>             request.setAttribute("struts.valueStack", null);

Not these lines but I guess you may also remove more things from
forwarded request (e.g. session). Could you please print
request.toString before these lines to see what type is it? Could you
serialize request to a xml to see all values stored in that request?
Anyway, like you, I also think this issue is because of forwarding the
request from Struts1 to Struts2.

Regards.


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: Struts2 login action class seems to be reused

Prasanth-2
Yes, login page is accessible always. Direct jsp access is not allowed, it has to go through the actions. When a user requests /Login.action login jsp page is displayed. When the user submits username
and password (Post to Login.action) the user is authenticated and home page is displayed by Login.action. Since the same action handles both displaying login page and validating, if the values are
already present (username, password, value of the button clicked) the action will authenticate the user and display home page as it does this it will make a database entry saying xyz user has logged in.

Actual Setup:
Application 1: /context1   --- User can login here and they will be forwarded to context2. This application uses struts 2.5.14
Application 2: /context2   --- User can login directly in /context 2 (in which case no forwarding). This application uses struts 2.3.34 for login and other actions. There are few actions in struts1 also.

For replicating the issue I was directly accessing /context2/Login.action. So /context1 was not used in testing. But the Login filter had the below lines to make sure forwarded requests from /context1
would work.

request.setAttribute("struts.actionMapping", new ActionMapping());
request.setAttribute("struts.valueStack", null);

The request object type is io.undertow.servlet.spec.HttpServletRequestImpl

Thanks,
Prasanth


On 03/03/2018 04:14 AM, Yasser Zamani wrote:

> On 3/3/2018 12:37 AM, Prasanth Pasala wrote:
>> I was able to replicate the issue today. Asked few users to keep logging in and ran jmeter to access login page, with out putting any username or password. Out of the 100 attempts 2 attempts were
>> successful in getting in with out username/password. I am seeing database login entries for these two. Which would happen only if a valid session is not present and user has provided username/password.
> Shouldn't login page being accessible always? How do you try access
> login page, calling directly to jsp? Or action? How do you authenticate
> that access try, via session values? Via request parameters and querying
> database?
>
>> Not sure if the behavior is a side effect of having the below lines.
>>
>>             request.setAttribute("struts.actionMapping", new ActionMapping());      
>>             request.setAttribute("struts.valueStack", null);
> Not these lines but I guess you may also remove more things from
> forwarded request (e.g. session). Could you please print
> request.toString before these lines to see what type is it? Could you
> serialize request to a xml to see all values stored in that request?
> Anyway, like you, I also think this issue is because of forwarding the
> request from Struts1 to Struts2.
>
> Regards.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

Reply | Threaded
Open this post in threaded view
|

Re: Struts2 login action class seems to be reused

Yasser Zamani-2


On 3/5/2018 7:48 PM, Prasanth wrote:
> But the Login filter had the below lines to make sure forwarded requests from /context1
> would work.
>
> request.setAttribute("struts.actionMapping", new ActionMapping());

Please let me discuss this line first of all. I'm still surprised how
context2 app works with this line! I expect you always get
ConfigurationException or get the result of the default action. Have you
set this filter pattern to being applied only on /Login.action? If so,
still you should get ConfigurationException or get the result of the
default action (is /Login.action default?). Or maybe you have put these
two lines in an if statement like if(request has these attributes){...}?
If not, then do this please; an if statement for each line.

Could you please try `request.setAttribute("struts.actionMapping",
null)`? then post back the exception if any (I don't expect any). You
should set to null or remove the attribute. Any other code is wrong.

Regards.


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: Struts2 login action class seems to be reused

adam brin
What are the annotations on the class?  Is it possible that you're using
Spring, and not declaring "prototype" scope. eg:

@Scope("prototype")

On Mon, Mar 5, 2018 at 10:49 AM, Yasser Zamani <[hidden email]>
wrote:

>
>
> On 3/5/2018 7:48 PM, Prasanth wrote:
> > But the Login filter had the below lines to make sure forwarded requests
> from /context1
> > would work.
> >
> > request.setAttribute("struts.actionMapping", new ActionMapping());
>
> Please let me discuss this line first of all. I'm still surprised how
> context2 app works with this line! I expect you always get
> ConfigurationException or get the result of the default action. Have you
> set this filter pattern to being applied only on /Login.action? If so,
> still you should get ConfigurationException or get the result of the
> default action (is /Login.action default?). Or maybe you have put these
> two lines in an if statement like if(request has these attributes){...}?
> If not, then do this please; an if statement for each line.
>
> Could you please try `request.setAttribute("struts.actionMapping",
> null)`? then post back the exception if any (I don't expect any). You
> should set to null or remove the attribute. Any other code is wrong.
>
> Regards.
>
>


--
_________________________________________________________
Adam Brin
Director of Technology, Digital Antiquity
480.965.1278
Reply | Threaded
Open this post in threaded view
|

Re: Struts2 login action class seems to be reused

Prasanth Pasala
In reply to this post by Yasser Zamani-2
I am not defining any default action.

I would get the below exception if I set the ActionMapping to null. For some reason the object doesn't go away, if I set it to null. After setting it to null using
request.setAttribute("struts.actionMapping", null);    I can get it using getAttribute. The object remains even if I do removeAttribute.

11:57:27,509 ERROR [stderr] (default task-32) Caused by: java.lang.ClassCastException: org.apache.struts2.dispatcher.mapper.ActionMapping cannot be cast to
org.apache.struts2.dispatcher.mapper.ActionMapping
11:57:27,509 ERROR [stderr] (default task-32)     at org.apache.struts2.dispatcher.ng.PrepareOperations.findActionMapping(PrepareOperations.java:163)
11:57:27,509 ERROR [stderr] (default task-32)     at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:92)
11:57:27,509 ERROR [stderr] (default task-32)     at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
11:57:27,509 ERROR [stderr] (default task-32)     at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
11:57:27,509 ERROR [stderr] (default task-32)     at com.xxxxx.xxxxxx.LoginFilter.doFilter(LoginFilter.java:52)
11:57:27,509 ERROR [stderr] (default task-32)     at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
11:57:27,510 ERROR [stderr] (default task-32)     at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
11:57:27,510 ERROR [stderr] (default task-32)     at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
11:57:27,510 ERROR [stderr] (default task-32)     at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
11:57:27,510 ERROR [stderr] (default task-32)     at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
11:57:27,510 ERROR [stderr] (default task-32)     at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
11:57:27,510 ERROR [stderr] (default task-32)     at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
11:57:27,510 ERROR [stderr] (default task-32)     at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
11:57:27,510 ERROR [stderr] (default task-32)     at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:274)
11:57:27,510 ERROR [stderr] (default task-32)     at io.undertow.servlet.handlers.ServletInitialHandler.dispatchToPath(ServletInitialHandler.java:209)
11:57:27,510 ERROR [stderr] (default task-32)     at io.undertow.servlet.spec.RequestDispatcherImpl.forwardImpl(RequestDispatcherImpl.java:221)
11:57:27,510 ERROR [stderr] (default task-32)     ... 128 more

Below is what I see by displaying the request.getAttribute("struts.actionMapping") after removeAttribute or after setting it to null.
ActionMapping{name='Login', namespace='/', method='null', extension='action', params={}, result=null}

In StrutsPrepareAndExecuteFilter below is the line that gets the action mapping, since the forceLookup is set to true the PrepareOperations class might be creating it again.
ActionMapping mapping = prepare.findActionMapping(request, response, true);


---------------PrepareOperations-------------------------------
public ActionMapping findActionMapping(HttpServletRequest request, HttpServletResponse response, boolean forceLookup) {
        ActionMapping mapping = (ActionMapping) request.getAttribute(STRUTS_ACTION_MAPPING_KEY);
        if (mapping == null || forceLookup) {
            try {
                mapping = dispatcher.getContainer().getInstance(ActionMapper.class).getMapping(request, dispatcher.getConfigurationManager());
                if (mapping != null) {
                    request.setAttribute(STRUTS_ACTION_MAPPING_KEY, mapping);
                }
            } catch (Exception ex) {
                if (dispatcher.isHandleException() || dispatcher.isDevMode()) {
                    dispatcher.sendError(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex);
                }
            }
        }

        return mapping;
    }
----------------------------------------------

Thanks,
Prasanth


On 03/05/2018 11:49 AM, Yasser Zamani wrote:

>
> On 3/5/2018 7:48 PM, Prasanth wrote:
>> But the Login filter had the below lines to make sure forwarded requests from /context1
>> would work.
>>
>> request.setAttribute("struts.actionMapping", new ActionMapping());
> Please let me discuss this line first of all. I'm still surprised how
> context2 app works with this line! I expect you always get
> ConfigurationException or get the result of the default action. Have you
> set this filter pattern to being applied only on /Login.action? If so,
> still you should get ConfigurationException or get the result of the
> default action (is /Login.action default?). Or maybe you have put these
> two lines in an if statement like if(request has these attributes){...}?
> If not, then do this please; an if statement for each line.
>
> Could you please try `request.setAttribute("struts.actionMapping",
> null)`? then post back the exception if any (I don't expect any). You
> should set to null or remove the attribute. Any other code is wrong.
>
> Regards.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

Reply | Threaded
Open this post in threaded view
|

Re: Struts2 login action class seems to be reused

Prasanth Pasala
In reply to this post by adam brin
I am not using Spring. Using Struts1, Struts 2 (2.3.34), tiles 2.0.4

On 03/05/2018 11:57 AM, Adam Brin wrote:

> What are the annotations on the class?  Is it possible that you're using
> Spring, and not declaring "prototype" scope. eg:
>
> @Scope("prototype")
>
> On Mon, Mar 5, 2018 at 10:49 AM, Yasser Zamani <[hidden email]>
> wrote:
>
>>
>> On 3/5/2018 7:48 PM, Prasanth wrote:
>>> But the Login filter had the below lines to make sure forwarded requests
>> from /context1
>>> would work.
>>>
>>> request.setAttribute("struts.actionMapping", new ActionMapping());
>> Please let me discuss this line first of all. I'm still surprised how
>> context2 app works with this line! I expect you always get
>> ConfigurationException or get the result of the default action. Have you
>> set this filter pattern to being applied only on /Login.action? If so,
>> still you should get ConfigurationException or get the result of the
>> default action (is /Login.action default?). Or maybe you have put these
>> two lines in an if statement like if(request has these attributes){...}?
>> If not, then do this please; an if statement for each line.
>>
>> Could you please try `request.setAttribute("struts.actionMapping",
>> null)`? then post back the exception if any (I don't expect any). You
>> should set to null or remove the attribute. Any other code is wrong.
>>
>> Regards.
>>
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: Struts2 login action class seems to be reused

Yasser Zamani-2
In reply to this post by Prasanth-2


On 3/5/2018 7:48 PM, Prasanth wrote:
> For replicating the issue I was directly accessing /context2/Login.action. So /context1 was not used in testing.

Please let me repeat what I understood; When some users are signed in
into /context1, you browses /context2/Login.action via JMeter empty
requests, but about 2 percent of them, successfully sign in into /context2!

Did I understand the issue correctly? If so, it's very odd ... and I
like strange issues :)

Does this issue also happen even when no one is signed in into
/context1? If so, does this issue also happen when /context1 is stopped
(i.e. /context2 never get any forwarded request from /context1 so far)?
I ask these to know if this issue is dependent to the app on /context1
or not.

I see you use Undertow web server and I reviewed it and saw it's highly
non-blocking async web server. Then ... please add a hidden field to
your login.jsp which it's value will be
request.getParameter("testIfStrutsReusesAction"). In JMeter add
testIfStrutsReusesAction=JMeter to your request parameters. Then re-run
JMeter and see if those two successful requests have a hidden field with
value "JMeter" in their response?? (also see that other requests must
have this hidden field elsewhere there is a problem in your impl of
these). I ask these to know if that successful response is really a
response for your JMeter request!

If none of above were helpful, then could you please share
/context2/Login.action? I need to see how do you authenticate? Only via
request params? Or session or something else makes sense also?

Regards.

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: Struts2 login action class seems to be reused

Yasser Zamani-2
In reply to this post by Prasanth Pasala


On 3/6/2018 9:42 PM, Prasanth Pasala wrote:
> In StrutsPrepareAndExecuteFilter below is the line that gets the action mapping, since the forceLookup is set to true the PrepareOperations class might be creating it again.
> ActionMapping mapping = prepare.findActionMapping(request, response, true);

Thanks a lot! This explains why you don't get an exception. So , please
let forget this sub-thread and following up the resolution on my another
email in main-thread.

Thanks.

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: Struts2 login action class seems to be reused

Prasanth-2
In reply to this post by Yasser Zamani-2
/context1 is used just for directing users to the right application (or context). Session is really maintained by /context2. Users can login directly in /context2 or they can input username and
password in /context1 and they will be forwarded to the right context on of which is /context2. So the login information could come to /context2/Login.action via a direct POST to this action or via a
forwarded request from /context1.

The testing I have done is completely on /context2. Have some users login at /context2/Login.action while JMeter tries to access /context2/Login.action and another action /context2/PlanList.action
(requests to any action other than Login.action will get forwarded to Login.action if the user is not yet logged in). So a direct request to /context/PlanList.action will end up at /context2/Login.action.

I can't say that 2 percent of users were able to get in without username/password. As I have ran the JMeter tests a lot of times (each run with 100 users). Only during one of those runs of JMeter I
had 2 requests get users home page when Login.action was requested (with out username/password).

Below is the Login.action code. Removed the code that fetches the data for home page.

Thanks,
Prasanth


public class LoginAction implements ServletRequestAware{

    Logger log = Logger.getLogger(this.getClass());
    private HttpServletRequest request;
   
    private String message  = "";
    private String username = "";
    private String password = "";
    private String action   = "";

   
    public String execute() throws Exception {
       
        String result = null;
        boolean displaySuccessPage = false;
       
       
        // SEE IF THE USER SESSION IS ALREADY THERE, IN WHICH CASE NO NEED TO DISPLAY LOGIN PAGE
        // MOVE TO SUCCESS PAGE
        Long censusID = null;
        HttpSession session = request.getSession(false);
        if(session != null) {
            if(session.getAttribute("username") != null && session.getAttribute("CensusID") != null) {
                // GET THE CENSUS ID AND DISPLAY SUCCESS PAGE
                censusID = (Long) session.getAttribute("CensusID");
                if(censusID != null & censusID > 0) {
                    // JUST MADE SURE THAT WE HAVE A VALID CENSUS ID
                    displaySuccessPage = true;
                }
            }
        }
       
        // IF ACTION IS LOGOUT THEN LOGOUT THE USER
        // OR IF THE USER DECLINES DISCLAIMER       
        if(  ("Logout".equals(action) || "Decline".equals(action)) ||
                (request.getParameter("Submit") != null && request.getParameter("Submit").trim().equals("Logout"))){
                       
            // INVALIDATE THE SESSION
            request.getSession().invalidate();
            message = "You have been successfully logged out";
            username = "";
            password = "";
            displaySuccessPage = false;
            result = "secure";
        }   
        // IF THE PARTICIPANT HAS ACCEPTED THE DISCLAIMER UPDATE THE DATABASE
        else if("Accept".equals(action)) {
            censusID = (Long) request.getSession().getAttribute("_CensusID");
            if(censusID != null) {
                Utils.updateDisclaimerCode(censusID);
                // SET THE USERNAME & CENSUSID. REMOVE THE TEMPORARY VARIABLES
                request.getSession().setAttribute("username", request.getSession().getAttribute("_username"));
                request.getSession().setAttribute("CensusID", request.getSession().getAttribute("_CensusID"));
                request.getSession().removeAttribute("_username");
                request.getSession().removeAttribute("_CensusID");
                request.getSession().setAttribute("dispContactInfo", Plans.getDisplayContactInfoCode(censusID));
                displaySuccessPage = true;
            }
        }
        // IF USER IS NOT ALREADY AUTHENTICATED
        else if(!displaySuccessPage){
            // IF USERNAME IS NOT PROVIDED DISPLAY LOGIN PAGE
            if(username.equals("")){
                request.getSession().setAttribute("maintenanceMessage", Utils.getMaintenanceMessage()[0]);
                request.getSession().setAttribute("suppressLogin", Boolean.parseBoolean(Utils.getMaintenanceMessage()[1]));
                result = "login";
            }
            else{
            // USER NAME SPECIFIED SO TRY TO AUTHENTICATE   
                //GET THE IPADDRESS OF THE CLIENT
                String remoteHost = request.getHeader("X-FORWARDED-FOR");
                if(remoteHost == null || "".equals(remoteHost.trim())) {
                    remoteHost = request.getRemoteAddr();
                }
                //AUTHENTICATE USER
                censusID = Utils.authenticate(username, password, remoteHost);
                if(censusID == -1) {
                    message = "Invalid username/password specified";
                    result = "failed";
                }
                else {
                    new com.xxxxx.xxxxx.model.Logger().loggedIn(censusID, remoteHost);
                    String[] maintenanceMessage = Utils.getMaintenanceMessage();
                    if(Boolean.parseBoolean(maintenanceMessage[1])) {
                        // SITE UNDER MAINTENANCE
                        request.getSession().setAttribute("maintenanceMessage", maintenanceMessage[0]);
                        request.getSession().setAttribute("suppressLogin", Boolean.parseBoolean(maintenanceMessage[1]));
                        message = "Website is under maintenance";
                        result = "failed";
                    }
                    else {
                        // USER HAS BEEN LOGGED IN SO CREATE A NEW SESSION
                        session = request.getSession();
                        session.setAttribute("username", username);
                        session.setAttribute("CensusID", new Long(censusID));
                        session.setAttribute("censusId", new Long(censusID));
                        session.setAttribute("dispContactInfo", Plans.getDisplayContactInfoCode(censusID));
                       
                        synchronized (request.getSession().getServletContext()) {
                            // INCREMENT THE USER COUNT
                            int userCount = 0;
                            if(request.getSession().getServletContext().getAttribute("userCount") != null) {
                                userCount = (Integer) request.getSession().getServletContext().getAttribute("userCount");
                            }
                            userCount++;
                            log.info("User Count:" + userCount);
                            request.getSession().getServletContext().setAttribute("userCount", userCount);   
                        }                                               
                        displaySuccessPage = true;
                    }
                }
            }
        }

           

        if(displaySuccessPage) {
        // CODE TO DISPLAY HOME PAGE
            xxxxxxxxxxxxxxxxxxxxxx
            xxxxxxxxxxxxxxxxxxxxxx
            xxxxxxxxxxxxxxxxxxxxxx       
        }
       
        // GET SITE NEWS ITEMS
        Calendar cal = Calendar.getInstance();
        LinkedHashMap<String, String> news = Plans.getNews(-1, new Date(cal.getTimeInMillis()));
        request.getSession().setAttribute("siteNews", news);
       
        return result;       
    }
   
    /**
     * Sets the client id and client name in the session.
     * @param censusId
     * @param request
     * @throws SQLException
     */
    private void setClientId(long censusId, HttpServletRequest request) throws SQLException {
        HashMap<Long,String> clientIdAndName = Utils.getClientIdAndName(censusId);
        if(clientIdAndName != null){
            for(Long clientID: clientIdAndName.keySet()){
                request.getSession().setAttribute("ClientID", clientID);
                request.getSession().setAttribute("ClientName",clientIdAndName.get(clientID));
            }
        }
    }

    @Override
    public void setServletRequest(HttpServletRequest request) {
        this.request = request;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getAction() {
        return action;
    }

    public void setAction(String action) {
        this.action = action;
    }
   
   
}



On 03/07/2018 04:22 AM, Yasser Zamani wrote:

>
> On 3/5/2018 7:48 PM, Prasanth wrote:
>> For replicating the issue I was directly accessing /context2/Login.action. So /context1 was not used in testing.
> Please let me repeat what I understood; When some users are signed in
> into /context1, you browses /context2/Login.action via JMeter empty
> requests, but about 2 percent of them, successfully sign in into /context2!
>
> Did I understand the issue correctly? If so, it's very odd ... and I
> like strange issues :)
>
> Does this issue also happen even when no one is signed in into
> /context1? If so, does this issue also happen when /context1 is stopped
> (i.e. /context2 never get any forwarded request from /context1 so far)?
> I ask these to know if this issue is dependent to the app on /context1
> or not.
>
> I see you use Undertow web server and I reviewed it and saw it's highly
> non-blocking async web server. Then ... please add a hidden field to
> your login.jsp which it's value will be
> request.getParameter("testIfStrutsReusesAction"). In JMeter add
> testIfStrutsReusesAction=JMeter to your request parameters. Then re-run
> JMeter and see if those two successful requests have a hidden field with
> value "JMeter" in their response?? (also see that other requests must
> have this hidden field elsewhere there is a problem in your impl of
> these). I ask these to know if that successful response is really a
> response for your JMeter request!
>
> If none of above were helpful, then could you please share
> /context2/Login.action? I need to see how do you authenticate? Only via
> request params? Or session or something else makes sense also?
>
> Regards.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

Reply | Threaded
Open this post in threaded view
|

Re: Struts2 login action class seems to be reused

Yasser Zamani-2


On 3/7/2018 7:34 PM, Prasanth wrote:
> I can't say that 2 percent of users were able to get in without username/password. As I have ran the JMeter tests a lot of times (each run with 100 users). Only during one of those runs of JMeter I
> had 2 requests get users home page when Login.action was requested (with out username/password).
>
> Below is the Login.action code. Removed the code that fetches the data for home page.

Thanks! I see you use session also.

Looks like a bug with Undertow web server [1]. I'm not familiar with it
so you may open an issue there and copy paste this thread there. They
may have some idea as it seems they have similar issues with session
which I linked below.

Good luck.

[1]
https://issues.jboss.org/browse/JBEAP-6683?focusedCommentId=13340535&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-13340535

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: Struts2 login action class seems to be reused

Prasanth Pasala
Thanks for looking into this Yasser.  In the current setup we have, we don't have a cluster, it is the only server handling all requests.

If it is a session crossover we would display another user information without making a login entry. In the cases where we had issue the code recognized that there is no active session and went to the
authentication part, authenticated the user and made a database entry for successful login. The authentication is based on the form variables populated by struts into the action class.

Thanks,
Prasanth

On 03/07/2018 01:22 PM, Yasser Zamani wrote:

>
> On 3/7/2018 7:34 PM, Prasanth wrote:
>> I can't say that 2 percent of users were able to get in without username/password. As I have ran the JMeter tests a lot of times (each run with 100 users). Only during one of those runs of JMeter I
>> had 2 requests get users home page when Login.action was requested (with out username/password).
>>
>> Below is the Login.action code. Removed the code that fetches the data for home page.
> Thanks! I see you use session also.
>
> Looks like a bug with Undertow web server [1]. I'm not familiar with it
> so you may open an issue there and copy paste this thread there. They
> may have some idea as it seems they have similar issues with session
> which I linked below.
>
> Good luck.
>
> [1]
> https://issues.jboss.org/browse/JBEAP-6683?focusedCommentId=13340535&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-13340535
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

Reply | Threaded
Open this post in threaded view
|

Re: Struts2 login action class seems to be reused

Yasser Zamani-2


On 3/7/2018 11:23 PM, Prasanth Pasala wrote:
> If it is a session crossover we would display another user information without making a login entry. In the cases where we had issue the code recognized that there is no active session and went to the
> authentication part, authenticated the user and made a database entry for successful login. The authentication is based on the form variables populated by struts into the action class.

Ahaa... so, currently the only thing I can imagine is maybe this issue
raises up when you have two simultaneous requests: one with
username/password parameters, the other without (and both without any
active session). Could you please verify this with a lot of such pair
simultaneous requests using JMeter? i.e. create two simultaneous
requests, one of them contains username/password, the other one does
not. Add an assertion to the other one which checks if issue occurs.
Then tell JMeter to run this pair a lot of times, concurrently.

I hope you'll be able to reproduce the issue which is the half of the
resolution :)

Regards.

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: Struts2 login action class seems to be reused

Prasanth Pasala
Wish I was able to consistently reproduce it. I have two thread groups in JMeter one thread group requests login page then logs in. Another thread group just requests login page. I have tried this
with 100 users, 250 users in each thread group. I have varied the ramp up times from 60sec to 300sec. I have been trying this for the last 10 days. I was successful in reproducing it only during one
run, which had 100 users and two of the requests for login page (no username/password) made login entries and got home page.

I will keep trying. If I can't reproduce it more often, one solution I am thinking of is comparing the username/password in the action class with the values in the request object itself. If they are
different I can send an email with the information and not login the user.

Thanks,
Prasanth

On 03/08/2018 03:13 AM, Yasser Zamani wrote:

>
> On 3/7/2018 11:23 PM, Prasanth Pasala wrote:
>> If it is a session crossover we would display another user information without making a login entry. In the cases where we had issue the code recognized that there is no active session and went to the
>> authentication part, authenticated the user and made a database entry for successful login. The authentication is based on the form variables populated by struts into the action class.
> Ahaa... so, currently the only thing I can imagine is maybe this issue
> raises up when you have two simultaneous requests: one with
> username/password parameters, the other without (and both without any
> active session). Could you please verify this with a lot of such pair
> simultaneous requests using JMeter? i.e. create two simultaneous
> requests, one of them contains username/password, the other one does
> not. Add an assertion to the other one which checks if issue occurs.
> Then tell JMeter to run this pair a lot of times, concurrently.
>
> I hope you'll be able to reproduce the issue which is the half of the
> resolution :)
>
> Regards.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

Reply | Threaded
Open this post in threaded view
|

Re: Struts2 login action class seems to be reused

Yasser Zamani-2


On 3/8/2018 6:42 PM, Prasanth Pasala wrote:
> Wish I was able to consistently reproduce it. I have two thread groups in JMeter one thread group requests login page then logs in. Another thread group just requests login page. I have tried this
> with 100 users, 250 users in each thread group. I have varied the ramp up times from 60sec to 300sec.

I think this is not heavy enough to force race condition on your web
server. Use only ones user which logs in and logs out in a loop. Then,
in another side, Increase users (threads) and decrease the ramp up time
as more as your system does not hang. I remember I was able to ramp up
300 users (threads) in 15 seconds at my system.

Regards.

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: Struts2 login action class seems to be reused

Prasanth Pasala
Ran tests with 1000 users logging in in 60sec while simultaneously 1000 users just requesting login page in 60 sec to see if any of them would get in with out username/password. No luck. System seems
to be working properly. Also tried increasing it to 2000 it still worked as it should with out the issue coming up.

Would hot deployments cause any issue?

Thanks,
Prasanth

On 03/08/2018 11:53 AM, Yasser Zamani wrote:

>
> On 3/8/2018 6:42 PM, Prasanth Pasala wrote:
>> Wish I was able to consistently reproduce it. I have two thread groups in JMeter one thread group requests login page then logs in. Another thread group just requests login page. I have tried this
>> with 100 users, 250 users in each thread group. I have varied the ramp up times from 60sec to 300sec.
> I think this is not heavy enough to force race condition on your web
> server. Use only ones user which logs in and logs out in a loop. Then,
> in another side, Increase users (threads) and decrease the ramp up time
> as more as your system does not hang. I remember I was able to ramp up
> 300 users (threads) in 15 seconds at my system.
>
> Regards.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

Reply | Threaded
Open this post in threaded view
|

Re: Struts2 login action class seems to be reused

Yasser Zamani-2


On 3/10/2018 1:22 AM, Prasanth Pasala wrote:
> Ran tests with 1000 users logging in in 60sec while simultaneously 1000 users just requesting login page in 60 sec to see if any of them would get in with out username/password. No luck. System seems
> to be working properly. Also tried increasing it to 2000 it still worked as it should with out the issue coming up.
>
> Would hot deployments cause any issue?

Without reproducing it, it's hard to say why this issue happens rarely
:( How did you discover it firstly? Was incorrectly loged in user able
to continue to other pages also as an authenticated user?

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: Struts2 login action class seems to be reused

Prasanth Pasala
We had a user report it soon after the deployment. After that we started looking into the specific user who reported (User1) and the user (whose information was seen by the reporting user) say User2.
We realized there are login entries from same IP for both of these users. In the access log of the server there was a POST request for User1 but at the time of login entry for User2 there was only a
GET request.  In the time line GET request is first, User1 sees User2's information logs out and then login again with their credentials.

Thanks,
Prasanth

On 03/13/2018 11:41 PM, Yasser Zamani wrote:

>
> On 3/10/2018 1:22 AM, Prasanth Pasala wrote:
>> Ran tests with 1000 users logging in in 60sec while simultaneously 1000 users just requesting login page in 60 sec to see if any of them would get in with out username/password. No luck. System seems
>> to be working properly. Also tried increasing it to 2000 it still worked as it should with out the issue coming up.
>>
>> Would hot deployments cause any issue?
> Without reproducing it, it's hard to say why this issue happens rarely
> :( How did you discover it firstly? Was incorrectly loged in user able
> to continue to other pages also as an authenticated user?
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

Reply | Threaded
Open this post in threaded view
|

Re: Struts2 login action class seems to be reused

Yasser Zamani-2


On 3/14/2018 5:43 PM, Prasanth Pasala wrote:
> We had a user report it soon after the deployment. After that we started looking into the specific user who reported (User1) and the user (whose information was seen by the reporting user) say User2.
> We realized there are login entries from same IP for both of these users.

As you get IP address from request (rather than Struts action), then it
seems that request (which contains username/password and that same IP
address) is being reused.

> In the access log of the server there was a POST request for User1 but at the time of login entry for User2 there was only a
> GET request.  In the time line GET request is first, User1 sees User2's information logs out and then login again with their credentials.

At that time when there is a GET request for User1 and this issue
happens, what are logs for User2 at same time?

Thanks in advance!

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]
12