Monday 18 January 2016

Struts2: Session management using custom interceptor, SessionAware interface

In every web application, we need to block some resources from unauthorized access. In this post, I am going to explain, how to restrict access to specific resources using custom interceptor, SessionAware interface. Our custom interceptor checks whether the request is authenticated request or not. If the request is authenticated request, then it allows access to users, else deny the access and redirect request to the login page.

Following are the files in brief.

File
Description
SessionInterceptor.java
Interceptor check for valid session for restricted resources.
LoginAction.java
Creates valid session.
login.jsp
Simple login page
restricted.jsp
Restricted resource. User must login to access this resource.
success.jsp
Once user logged in successful, it redirects to success.jsp page

Following step-by-step procedure explains simple application that uses an interceptor to maintain session.

Step 1: Create new dynamic web project ‘struts2_session’ in Eclipse.
File -> New -> Dynamic Web Project.

Step 2: Mavenize the project. Right click the project -> Properties -> Configure -> Convert To Maven Project.
Open pom.xml, update struts2 maven dependencies. I am going to use following maven dependency.
<dependency>
 <groupId>org.apache.struts</groupId>
 <artifactId>struts2-core</artifactId>
 <version>2.3.20</version>
</dependency>

Step 3: Define login.jsp like below.

login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
 <form method="post" action="loginCheck">
  User name: <input type="text"  name="userName" /> <br />
  Password: <input type="password" name="password" /> <br />
  <input type="submit" value="submit" /> 
 </form>
</body>
</html>


Step 4: Define restricted.jsp like below.
restricted.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
 <h1>Restricted page</h1>
</body>
</html>


Define success.jsp like below.
success.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
 <h1>Login Successful</h1>
</body>
</html>


Step 5: Define package com.sample. Define the class LoginAction.java.

LoginAction.java

package com.sample;

import java.util.Map;

import org.apache.struts2.dispatcher.SessionMap;
import org.apache.struts2.interceptor.SessionAware;

public class LoginAction implements SessionAware {
 private SessionMap<String, Object> session;
 private String userName;
 private String password;

 public String execute() {
  return "success";
 }
 
 public String getRestricted(){
  return "success";
 }

 public String checkLogin() {
  if(userName.equals("admin") && password.equals("admin")){
   session.put("userName", userName);
   return "success";
  }
  
  return "input";
 }

 @Override
 public void setSession(Map<String, Object> session) {
  this.session = (SessionMap) session;
 }

 public String logout() {
  session.invalidate();
  return "success";
 }

 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;
 }

}
LoginAction class implements SessionAware interface. The SessionAware interface has one method, setSession, that your Action class will need to override. The Struts 2 framework has an interceptor that will inject the HTTP session object into the Action class by calling the setSession method. When your Action class needs to access the HTTP session object implement the SessionAware interface and override the setSession method


Step 6: Define SessionInterceptor like below.
SessionInterceptor.java

package com.sample;

import java.util.Map;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;

public class SessionInterceptor implements Interceptor {

 @Override
 public void destroy() {
  // TODO Auto-generated method stub

 }

 @Override
 public void init() {
  // TODO Auto-generated method stub

 }

 @Override
 public String intercept(ActionInvocation invocation) throws Exception {
  Map<String, Object> session = invocation.getInvocationContext()
    .getSession();

  String userName = (String) session.get("userName");

  if (userName == null || !userName.equals("admin")) {
   return "loginUser";
  }
  return invocation.invoke();
 }

}


Step 7: Update web.xml like below.
web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
 <display-name>struts2_token</display-name>
 <welcome-file-list>
  <welcome-file>index.html</welcome-file>
  <welcome-file>index.htm</welcome-file>
  <welcome-file>index.jsp</welcome-file>
  <welcome-file>default.html</welcome-file>
  <welcome-file>default.htm</welcome-file>
  <welcome-file>default.jsp</welcome-file>
 </welcome-file-list>
 <filter>
  <filter-name>struts2</filter-name>
  <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
 </filter>
 <filter-mapping>
  <filter-name>struts2</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>
</web-app>


Step 8: It is time to create struts.xml. Since Struts 2 requires struts.xml to be present in classes folder. Create struts.xml file under the WebContent/WEB-INF/classes folder. Eclipse does not create the "classes" folder by default, so you need to do this yourself. To do this, right click on the WEB-INF folder in the project explorer and select New > Folder. Create struts.xml file inside classes.

struts.xml

<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>
 <package name="default" extends="struts-default">
  
  <interceptors>
   <interceptor name="userSession"
   class="com.sample.SessionInterceptor"></interceptor>
  </interceptors>
  
  <global-results>
   <result name="loginUser" type="redirect">/login</result>
  </global-results>
  
  <action name="loginCheck" class="com.sample.LoginAction" method="checkLogin">
   <result name="success">/success.jsp</result>
   <result name="input">/login.jsp</result>
  </action>
  
  <action name="login" class="com.sample.LoginAction">
   <result name="success">/login.jsp</result>
  </action>
  
  <action name="restricted" class="com.sample.LoginAction" method="getRestricted">
   <interceptor-ref name="userSession"></interceptor-ref>
   <result name="success">/restricted.jsp</result>
  </action>
  
  <action name="logout" class="com.sample.LoginAction" method="logout">
   <result name="success">/login.jsp</result>
  </action>
 </package>
</struts>


Observe struts.xml, I added the interceptor userSession, to the action 'restricted', so all the request that tries to access this action must go through the interceptor first.

Following is the complete project structure.

 

Run the application on server. Try to access the url ‘http://localhost:8080/struts2_session/restricted’ it redirects to login page, once you logged in successfully, you can able to access the restricted url.










Previous                                                 Next                                                 Home

1 comment:

  1. I need to know that if there will be 100 jsp pages. Then we have to use this interceptor line in struts.xml for every jsp pages.

    ReplyDelete