Using Interceptor to check user access rights
I am trying to use Interceptor
to prevent users from performing certain actions.
ContainsKeyInterceptor
:
public class ContainsKeyInterceptor extends AbstractInterceptor implements SessionAware {
private static final long serialVersionUID = 1L;
private Map<String, Object> session;
@Override
public String intercept(ActionInvocation actionInvocation) throws Exception {
if(session == null) {
System.out.println("session is null");
}
if(session.containsKey("currentId")) {
return "index";
}
String result = actionInvocation.invoke();
return result;
}
@Override
public void setSession(Map<String, Object> session) {
this.session = session;
}
}
It is supposed to redirect the user to the index page if currentId
found in session
.
However I get NullPointerException
it saying it session
is null as checked by if-check.
struts.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.devMode" value="false" />
<!-- actions available to guests -->
<package name="guest" extends="struts-default">
<interceptors>
<interceptor name="containskeyinterceptor" class="com.mypackage.interceptor.ContainsKeyInterceptor" />
</interceptors>
<action name="index" class="com.mypackage.action.IndexAction">
<interceptor-ref name="containskeyinterceptor" />
<result type="redirect">/index.jsp</result>
<result name="index" type="redirect">/index.jsp</result>
</action>
<action name="login" class="com.mypackage.action.LoginAction">
<interceptor-ref name="containskeyinterceptor" />
<result type="redirect">/index.jsp</result>
<result name="input">/login.jsp</result>
<result name="index" type="redirect">/index.jsp</result>
</action>
</package>
<!-- actions available to members -->
<package name="member" extends="struts-default">
<action name="logout" class="com.mypackage.action.LogoutAction">
<result type="redirectAction">
<param name="actionName">index</param>
</result>
</action>
</package>
</struts>
Why null session
and how to solve it?
( This was the link I used.)
source to share
Struts Session is just a Map<String,Object>
wrapper around the base HttpSession
.
When implementing the SessionAware interface, this is the correct way to get it into Action , if you want to get it from the Interceptor, you need to do the following:
To get the Struts table of the session :
@Override
public String intercept(ActionInvocation ai) throws Exception {
final ActionContext context = ai.getInvocationContext();
// Struts Session
Map<String, Object> session = context.getSession();
To get the real HttpSession object :
@Override
public String intercept(ActionInvocation ai) throws Exception {
final ActionContext context = ai.getInvocationContext();
HttpServletRequest request = (HttpServletRequest)context.get(StrutsStatics.HTTP_REQUEST);
// Http Session
HttpSession session = request.getSession();
However, the reason you are not getting the session (nor any other parameter, object, etc.) in your actions is because you run into a common error: only apply one Interceptor (yours) instead of applying the whole Interceptor Stack (which yours should contain):
You can define it twice in each action:
<action name="login" class="ph.edu.iacademy.action.LoginAction">
<interceptor-ref name="defaultStack" /> <!-- this is missing -->
<interceptor-ref name="containskeyinterceptor" />
or, much better, define it once on the custom stack and always use the stack:
<interceptors>
<interceptor-stack name="yourStack">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="containskeyinterceptor"/>
</interceptor-stack>
</interceptors>
<action name="login" class="ph.edu.iacademy.action.LoginAction">
<interceptor-ref name="yourStack" />
and ultimately define it with ref-interceptor-ref so you don't have to write it for every config file of that package:
<default-interceptor-ref name="yourStack"/>
<action name="login" class="ph.edu.iacademy.action.LoginAction">
source to share
Based on this I don't think the interceptor itself can / should be session aware.
You can access this property as such:
final ActionContext context = actionInvocation.getInvocationContext();
this.session = context.getSession();
There might be a way to get this set automatically, I'm not too familiar with struts2, but it might be that sessionaware only works for a certain subset of objects, and this interceptor is not one of them for some reason, (not scanned, excluded from scanning , wrong type)
source to share