Friday, December 19, 2008

Page-Level Access Controls in Struts 2 - Part 2

Background

Applications should ensure users are properly authenticated and have sufficient permissions to access pages before content is displayed. Page-level access controls are one security control that enforces this behavior.

Part 1 and 2 of this article describes one of many ways to implement a Struts 2 AuthenticationInterceptor and a RolesInterceptor to verify users have authenticated successfully and belong to an approved role before allowing access to pages. The key features targeted by both interceptors include a default deny policy and a centralized location for defining access control rules.

Struts 2 RolesInterceptor

In Part 2 of the page-level access controls article, a RolesInterceptor has been added to the struts.xml file. The "roleActions" parameter, passed to the interceptor, contains a list of actions allowed for each role. The "*" role indicates that any role can access the action.

Struts.xml

(Click the image above to view the XML)

Similar to the AuthenticationInterceptor, the RolesInterceptor verifies all users are allowed access to a particular page or validates that the user's "role" session variable matches one of the roles allowed for the action requested.

RolesInterceptor
(Click the image above to view the code)

In the ProcessSimpleLogin action, the "role" session variable has been added to include the name of the role that the user belongs to.

ProcessSimpleLogin

(Click the image above to view the code)

8 comments:

Anonymous said...

Thank you very much for your help!

Anonymous said...

Good article, very interesting !
I've got a question : you set permission on action (ex. : the action Internal), right. This action only return the Internal jsp. How is it possible to secure a direct access to this jsp by the URL ?. Sorry for my poor english.

P.M from France

Nick Coblentz said...

The key is that the JSPs are put in a non web accessible directory. In this case these JSPs are in /WEB-INF/pages/. The web accessible directory for this particular project was /WebContent.

Anonymous said...

Thaks for your reply ! I understand. I've got another question about that : how can i have a submit button or a link wich could forward to a JSP put in a non accessible WEB-INF directory ? An s:url / s:a can reference directly an JSP wich is accessible but not an JSP put in non acessible directory. Is the only way is to forward to an action wich result is the JSP ?

Nick Coblentz said...

If you have a submit button, I am guessing you are submitting some sort of form and wish to do some processing. I recommend doing the processing within a struts 2 action rather than in the JSP (implementing a proper Model-View-Controller architecture).

In most cases, I wouldn't recommend putting pages that require authorization within a web accessible directory. It makes it more difficult (but not impossible) to apply a standard, centralized access control method uniformly across the application. That said, you could always call a function within each JSP that verifies users' authorization before displaying the page or performing any processing.

With the current implementation of this control, it would be necessary to forward to an action in order to utilize the page-level access control and to display a JSP within a non-web accessible directory.

Anonymous said...

I fully agree with your point of view, as it is a good practice to forward to an action (wich could use interceptor).
My problem is the one : on a login page, i want a "forgotten password" link (s:a). This link should display an JSP put in a non accessible WEB-INF directory. This JSP should allow user to post userId and email to receive his password by mail. This JSP has validation feature (by xml file).
If the link on my login page forward to an action to simply display the "forgotten password" JSP, this JSP is validated every time it's displayed . I want this only when i submit its content.
Hope you could help me.

Nick Coblentz said...

Try choosing to perform validation based on whether it is a GET request or a POST request.

For example, if you extended a base action like the following:

http://struts2securityaddons.googlecode.com/svn/trunk/Struts2SecurityAddons/src/java/com/nickcoblentz/struts2/actions/BaseAction.java

You could do something like this in the action:

public String execute() {
if(isPostRequest()) {
//do some validation here
return SUCCESS
}

return INPUT;
}

Anonymous said...

What quick responses ! I understand. Not another way to "disable" the validation when i simply display the jsp for the first time ? That's why i wanted to have a link wich forward directly to my jsp but it seems to be impossible if the jsp is put in non accessible WEB-INF directory ...