Struts2. After logging out of the account, you can still log on to the action in the address bar (enter the address in the browser to bypass verification). struts2action
Not much nonsense. Let's start with a question.
Problem: Use struts2 and spring to log on as a user and click it to log out.
The login page is very simple, probably like the following
The login action and logout action are configured as follows in strut. xml:
<Action name = "checkUser" class = "checkUserAction" method = "execute"> // here class = "checkUserAction" is the bean in the obtained spring configuration file.
<Result name = "login">/WEB-INF/jsp/login. jsp </result> // If logon fails, it will return to the login page again
<Result name = "success">/WEB-INF/jsp/list/home. jsp </result> // If the logon is successful, the welcome page is displayed.
</Action>
<Action name = "quitUser" class = "checkUserAction" method = "quitUser"> // the logged-out action. The logon page is displayed after the cancellation is successful.
<Result name = "success">/WEB-INF/jsp/login. jsp </result>
</Action>
The spring configuration file is as follows:
<bean id="administrator" class="pojo.Administrator"> </bean> <bean id="checkUserAction" class="action.checkUserAction" scope="prototype"> <property name="adminer"> <ref bean="administrator"/> </property> <property name="adminUserService"> <ref bean="adminUserServiceImpl"/> </property> </bean>
The source code of checkUserAction is as follows:
Public class checkUserAction extends ActionSupport implements ModelDriven <Administrator> {Administrator adminer; AdminUserService adminUserService; @ Override public String execute () throws Exception {String result = adminUserService. findAdministrator (adminer); // the line here is a comparison between the user name and password submitted in the form and in the database. If it succeeds, it is placed into the session, if the request fails, a prompt is displayed. if (! Result. equals ("success") {if (result. equals (AdminUserService. NOT_EXIST) {ServletActionContext. getRequest (). setAttribute ("error", "user name does not exist");} else if (result. equals (AdminUserService. WRONG_PASSWORD) {ServletActionContext. getRequest (). setAttribute ("error", "Incorrect password");} return "login";} ActionContext. getContext (). getSession (). put ("adminUser", adminer); return result ;}
/* The following is the method used to log out of the user. Clear the session */public String quitUser () throws Exception {ActionContext. getContext (). getSession (). clear (); return "success ";}...... the get and set methods are omitted, and the model-driven part is also omitted}
It's such a simple program. It's okay to log on and exit normally. But here I findA serious problem,
After clicking exit, I directly enter the action address in the address bar: "http: // localhost: 8080/xxx/checkUser" to bypass the "login" button, during direct access, you can log on to the welcome page normally !!!
This problem has plagued me for a long time and I have checked many methods on the Internet:
1. Some people say that they need to set up an interceptor. By blocking illegal login users in the interceptor, they can do so. Later, I tried not to do it.
2. also, to disable dynamic access, I found that my page itself is the method in the action that disables dynamic access by default. (The name of the directly accessed action, not the method in the accessed action ).
3. I checked again to see that struct2 can directly shield the method of directly entering the action name in the address bar for access. It seems that this method is also available in meters, that is to say, you can enter the action name directly in the address bar to access it!
For further analysis, I added a print in checkUserAction to directly print the data in the adminer object (that is, the username and password) used to obtain the form data, the value is correct. then I was puzzled. I had to log out and checked through the strut2 label <s: debug/>. There was indeed nothing in the session, but when you access the checkUser action in the address bar, there is still a value in the adminer object! Instead of clicking the form login button, I access the page by directly accessing the action in the address bar. who submitted the correct data? Then, I opened the browser's packet capture tool and found that when I accessed the action directly, it did not include any form (username and password) information, who installed the value?
I then wondered whether the model driver did anything bad? When I quit the model driver, I loaded the user name and password and sent it back to the browser. But then I checked the model driver source code, the model driver only pushes the obtained form data to the value stack before the action is executed. After the action is executed, nothing is done. I also did this operation. In the quitUser () function, before returning "success", I cleared all the content in the value stack. However, the problem persists !!!
Finally, I suddenly found a problem. Since the action address is directly accessed through the address bar, it is impossible to submit the form data, and the data in the session is also cleared, which can only indicate one problem, the value in the adminer object must be assigned by the server! So naturally, it must be the question of spring. cause: When spring generates an action object, it should be multi-instance, that is, every request will generate an action object, which is no problem. however, the problem is that when I configure checkUserAction, I did not assign the adminer object to multiple instances, resulting in the next action, the adminer object returned by spring to action is still the adminer object that was previously successfully logged on. This object still stores the username and password information for the last successful logon. Therefore, when you access the address bar directly, it uses the previous object for verification. Of course, it can pass. this is the root cause of the problem.
In fact, it has been verified that I access the checkUser Action through the address bar. On the logon page, the <s: debug/> switch is turned on. After each access, the value of the adminer object stored in the session has never changed.
Therefore, you only need<Bean id = "administrator" class = "pojo. Administrator" scope = "prototype"> change the following line to multiple instances.