Showing posts with label web application. Show all posts
Showing posts with label web application. Show all posts

Monday, March 29, 2010

Executing Asynchronous Actions in a Web Application

Web applications need to provide instant response to end users, however not all requests can be served instantly due to a variety of constraints on infrastructure the application must live with. In an enterprise web applications there could a variety of long running tasks initiated by user request. To handle such task, the request could be queued for later processing and user is presented with a message to check status at a later time.  For some requests a part of necessary processing could be done instantly and remaining could be done at a later time.

Queuing a request requires adding extra infrastructure to web applications. Request could be queued in a single instance of share data structure across the application. Application threads running in background can read the queue data structure and act on queue messages. Rather than writing this framework/infrastructure enterprise class open source libraries could be utilized.  ActiveMQ provides a robust queuing solution and Apache Camel provides processing queued actions. Both libraries can be used in embedded or standalone fashion.

Architecture:

ServletContextListener initialize the ActiveMQ Broker and CamelContext, queues and routes are setup.

Have web action/controller write to ActiveMQ queue.

Write classes/camel routes to read from queue .

Saturday, July 18, 2009

Web App + Security + Struts2

When securing a web application there are few options for authentication and authorization of user/roles. You could write your custom logic, use container managed security, or use 3rd part libraries, or augment container managed security with custom logic.

Custom Security: Custom security is implemented by writing programming logic. For a pure Struts2 app (Where every url of the web application is served by Struts actions), typically user is authenticated using a custom HTML form backed by a custom LoginAction. LoginAction will validated username/password and then store the user information in session variable. This user/role information stored in session can be used control the logic for what URL/actions can be accessed by user. You can write a Struts2 interceptor and have every single request for struts2 resource go through this interceptor. When user tries to access a resource in the application, this interceptor will check if user is not logged by looking at certain data in user session. If data is not found user can redirected to login action. If user is logged in then you can check the role to make sure user has access to the resource, once the action is executed, you can use the user role information in view code (JSPs or other ) to hide/show certain section of view.

Disadvantage of above approach is is that only struts actions are protected. Another approach will be to write a Servlet filter instead of a struts Interceptor. Other disadvantage is you will end up with lot of logic for protecting different url for various roles. You may write code to read a custom configuration file.

Following is sample code

struts.xml
---------------

<package extends="struts-default">

<interceptors>
<interceptor name="login" class="mypkg.AuthenticationInterceptor"/>
<interceptor-stack name="intStack">
<interceptor-ref name="login"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>

<default-interceptor-ref name="intStack"/>

Login form
---------------
<s:form action="login">
<table> <tr> <td >Username:</td> </tr>
<tr><td><s:textfield name="username"/></td> </tr>
<tr><td>Password:</td> </tr>
<tr><td><s:password label="Password" name="password"/></td></tr>
<tr><td><s:submit value="Login" /></td></tr>
</table>
</s:form>


LoginAction
----------------

public class LoginAction {

private User user;
private String username;
private String password;

public String execute() throws Exception {
Map session = ActionContext.getContext().getSession();

if (username == null) {
return "login";
}
user = yourDAO.getUser(username, password);
if (user != null) {
session.put("user", user);
return SUCCESS;
}
else {
return "login";
}
}
public void setUsername(String username){
this.username = username;
}
public String getUsername() {
return username;
}
public void setPassword(String password){
this.password = password;
}
public String getPassword() {
return password;
}
}



Interceptor code
----------------------

public class AuthenticationInterceptor implements Interceptor {

public String intercept(ActionInvocation invocation) throws Exception {

Map session = ActionContext.getContext().getSession();

//Check by looking at user's http session for certain data which you
// If not logged in redirect user to login.action
if (!session.containsKey("user") && !ActionContext.getContext().getName().equals("login")) {
return "login";
}

// If user is logged in then vcheck if user has access to requested url

String result = invocation.invoke();
return result;

}

}


Container managed security + Custom security: Servlet specification provides declarative security, access to web resources can be defined in web.xml. Once user is authenticated application servlet API could be used to access authenticated user / role information. Struts2 action can also be restricted to certain roles declarative style. One drawback is Roles information needs to be maintained in web.xml, If your application creates roles dynamically, new roles have to be also specified in web.xml (Needs rebuilding war file/application restart).


<security-constraint>
<web-resource-collection>
<web-resource-name>SecuredPages</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>

<security-role>
<description>Role required to see admin pages.</description>
<role-name>admin</role-name>
</security-role>
<security-role>
<description>Role with read only.</description>
<role-name>reader</role-name>
</security-role>

For autheticating form authentication can be used with a jsp specified in web.xml, the jsp includes a form action j_security_check. username/password are validated against the realm specified in web.xml. Realm represents the source of username/password and associated roles. There are a wide variety of Realms (JDBC, JNDI, xml file, Datasource) which are specific to servlet containers. For a web application deployed in Tomcat Realm is specified in context.xml under META-INF/ direcotory

<login-config>
<auth-method>FORM</auth-method>
<realm-name>JDBCRealm</realm-name>
<form-login-config>
<form-login-page>/login2.jsp</form-login-page>
<form-error-page>/error.jsp</form-error-page>
</form-login-config>
</login-config>
Login form
----------

<s:form action="j_security_check">
<table> <tr> <td >Username:</td> </tr>
<tr><td><s:textfield name="j_username"/></td> </tr>
<tr><td>Password:</td> </tr>
<tr><td><s:password label="Password" name="j_password"/></td></tr>
<tr><td><s:submit value="Login" /></td></tr>
</table>
</s:form>

META-INF/context.xml, login action will be validated against following Realm
-------------------------------------------------------------------------
<Context>
<Realm className="org.apache.catalina.realm.JDBCRealm"
driverName="org.gjt.mm.mysql.Driver"
connectionURL="jdbc:mysql://mydbserver/mydb_test2"
connectionName="myuser" connectionPassword="mypassword"
userTable="users" userNameCol="email"
userCredCol="password" digest="MD5"
userRoleTable="user_roles" roleNameCol="name"/>
</Context>


Above setup will provide for authentication and authorization for URL in web applications.

If you application requires further restrictions on struts Actions based on user roles, roles interceptor could be used and security could be declared in struts.xml.

Any further customization could be programmed by writing additional struts interceptors or servlet filters. Following is an example of custom interceptor where a different struts result/view is presented to user based on role.

public class ReaderViewInterceptor implements Interceptor{

public void destroy() {
}

public void init() {
}

public String intercept(ActionInvocation invocation) throws Exception {

invocation.addPreResultListener(new PreResultListener() {
public void beforeResult(ActionInvocation invocation, String resultCode) {
Map resultsMap = invocation.getProxy().getConfig().getResults();
if( ServletActionContext.getRequest().isUserInRole("Reader") ) {
invocation.setResultCode("readonly_" + resultCode);
}
}
});

String result = invocation.invoke();
return result;
}

}

Web App + Security + Struts2

When securing a web application there are few options for authentication and authorization of user/roles. You could write your custom logic, use container managed security, or use 3rd part libraries, or augment container managed security with custom logic.

Custom Security: Custom security is implemented by writing programming logic. For a pure Struts2 app (Where every url of the web application is served by Struts actions), typically user is authenticated using a custom HTML form backed by a custom LoginAction. LoginAction will validated username/password and then store the user information in session variable. This user/role information stored in session can be used control the logic for what URL/actions can be accessed by user. You can write a Struts2 interceptor and have every single request for struts2 resource go through this interceptor. When user tries to access a resource in the application, this interceptor will check if user is not logged by looking at certain data in user session. If data is not found user can redirected to login action. If user is logged in then you can check the role to make sure user has access to the resource, once the action is executed, you can use the user role information in view code (JSPs or other ) to hide/show certain section of view.

Disadvantage of above approach is is that only struts actions are protected. Another approach will be to write a Servlet filter instead of a struts Interceptor. Other disadvantage is you will end up with lot of logic for protecting different url for various roles. You may write code to read a custom configuration file.

Following is sample code

struts.xml
---------------

<package extends="struts-default">

<interceptors>
<interceptor name="login" class="mypkg.AuthenticationInterceptor"/>
<interceptor-stack name="intStack">
<interceptor-ref name="login"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>

<default-interceptor-ref name="intStack"/>

Login form
---------------
<s:form action="login">
<table> <tr> <td >Username:</td> </tr>
<tr><td><s:textfield name="username"/></td> </tr>
<tr><td>Password:</td> </tr>
<tr><td><s:password label="Password" name="password"/></td></tr>
<tr><td><s:submit value="Login" /></td></tr>
</table>
</s:form>


LoginAction
----------------

public class LoginAction {

private User user;
private String username;
private String password;

public String execute() throws Exception {
Map session = ActionContext.getContext().getSession();

if (username == null) {
return "login";
}
user = yourDAO.getUser(username, password);
if (user != null) {
session.put("user", user);
return SUCCESS;
}
else {
return "login";
}
}
public void setUsername(String username){
this.username = username;
}
public String getUsername() {
return username;
}
public void setPassword(String password){
this.password = password;
}
public String getPassword() {
return password;
}
}



Interceptor code
----------------------

public class AuthenticationInterceptor implements Interceptor {

public String intercept(ActionInvocation invocation) throws Exception {

Map session = ActionContext.getContext().getSession();

//Check by looking at user's http session for certain data which you
// If not logged in redirect user to login.action
if (!session.containsKey("user") && !ActionContext.getContext().getName().equals("login")) {
return "login";
}

// If user is logged in then vcheck if user has access to requested url

String result = invocation.invoke();
return result;

}

}


Container managed security + Custom security: Servlet specification provides declarative security, access to web resources can be defined in web.xml. Once user is authenticated application servlet API could be used to access authenticated user / role information. Struts2 action can also be restricted to certain roles declarative style. One drawback is Roles information needs to be maintained in web.xml, If your application creates roles dynamically, new roles have to be also specified in web.xml (Needs rebuilding war file/application restart).


<security-constraint>
<web-resource-collection>
<web-resource-name>SecuredPages</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>

<security-role>
<description>Role required to see admin pages.</description>
<role-name>admin</role-name>
</security-role>
<security-role>
<description>Role with read only.</description>
<role-name>reader</role-name>
</security-role>

For autheticating form authentication can be used with a jsp specified in web.xml, the jsp includes a form action j_security_check. username/password are validated against the realm specified in web.xml. Realm represents the source of username/password and associated roles. There are a wide variety of Realms (JDBC, JNDI, xml file, Datasource) which are specific to servlet containers. For a web application deployed in Tomcat Realm is specified in context.xml under META-INF/ direcotory

<login-config>
<auth-method>FORM</auth-method>
<realm-name>JDBCRealm</realm-name>
<form-login-config>
<form-login-page>/login2.jsp</form-login-page>
<form-error-page>/error.jsp</form-error-page>
</form-login-config>
</login-config>
Login form
----------

<s:form action="j_security_check">
<table> <tr> <td >Username:</td> </tr>
<tr><td><s:textfield name="j_username"/></td> </tr>
<tr><td>Password:</td> </tr>
<tr><td><s:password label="Password" name="j_password"/></td></tr>
<tr><td><s:submit value="Login" /></td></tr>
</table>
</s:form>

META-INF/context.xml, login action will be validated against following Realm
-------------------------------------------------------------------------
<Context>
<Realm className="org.apache.catalina.realm.JDBCRealm"
driverName="org.gjt.mm.mysql.Driver"
connectionURL="jdbc:mysql://mydbserver/mydb_test2"
connectionName="myuser" connectionPassword="mypassword"
userTable="users" userNameCol="email"
userCredCol="password" digest="MD5"
userRoleTable="user_roles" roleNameCol="name"/>
</Context>


Above setup will provide for authentication and authorization for URL in web applications.

If you application requires further restrictions on struts Actions based on user roles, roles interceptor could be used and security could be declared in struts.xml.

Any further customization could be programmed by writing additional struts interceptors or servlet filters. Following is an example of custom interceptor where a different struts result/view is presented to user based on role.

public class ReaderViewInterceptor implements Interceptor{

public void destroy() {
}

public void init() {
}

public String intercept(ActionInvocation invocation) throws Exception {

invocation.addPreResultListener(new PreResultListener() {
public void beforeResult(ActionInvocation invocation, String resultCode) {
Map resultsMap = invocation.getProxy().getConfig().getResults();
if( ServletActionContext.getRequest().isUserInRole("Reader") ) {
invocation.setResultCode("readonly_" + resultCode);
}
}
});

String result = invocation.invoke();
return result;
}

}