Works with SSLInterceptor plugin for Struts2
Configuration in the struts.xml
RequestUtil.java
Configuration in the struts.xml
package mycom.myapp.ssl;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
public class RequestUtil {
public static String buildQueryString(HttpServletRequest request) {
// add query string, if any
String queryString = request.getQueryString();
StringBuffer finalQs = new StringBuffer();
if (queryString != null && queryString.length() != 0) {
finalQs.append(queryString);
} else {
queryString = RequestUtil.getRequestParameters(request);
if (queryString != null && queryString.length() != 0) {
finalQs.append(queryString);
}
}
return finalQs.length()== 0 ? null : finalQs.toString();
}
public static String getRequestParameters(HttpServletRequest aRequest) {
return createQueryStringFromMap(aRequest.getParameterMap(), "&", aRequest).toString();
}
public static StringBuffer createQueryStringFromMap(Map m, String ampersand, HttpServletRequest req) {
StringBuffer aReturn = new StringBuffer("");
Set aEntryS = m.entrySet();
Iterator aEntryI = aEntryS.iterator();
while (aEntryI.hasNext()) {
Map.Entry aEntry = (Map.Entry) aEntryI.next();
Object value = aEntry.getValue();
String[] aValues = new String[1];
if (value == null) {
aValues[0] = "";
} else if (value instanceof List) { // Work around for Weblogic 6.1sp1
List aList = (List) value;
aValues = (String[]) aList.toArray(new String[aList.size()]);
} else if (value instanceof String) { // Single value from Struts tags
aValues[0] = (String) value;
} else { // String array, the standard returned from request.getParameterMap()
aValues = (String[]) value; // This is the standard
}
for (int i = 0; i < aValues.length; i++) {
append(aEntry.getKey(), aValues[i], aReturn, ampersand, req);
}
}
return aReturn;
}
private static StringBuffer append(Object key, Object value, StringBuffer queryString, String ampersand, HttpServletRequest req) {
if (queryString.length() > 0) {
queryString.append(ampersand);
}
// NTS: remove URLEncoder - causes symbols to be stored as hex values
queryString.append(key.toString());
queryString.append("=");
queryString.append(value.toString());
return queryString;
}
}
Secured.java
package mycom.myapp.ssl;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
//@Target(METHOD)
public @interface Secured { }
SSLInterceptor.java
package mycom.myapp.ssl;
//http://code.google.com/p/struts2-ssl-plugin/wiki/HowToUse
//Java API imports
import java.lang.reflect.Method;
import java.net.URI;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.apache.struts2.StrutsStatics;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
//Commons API imports
//Struts API imports
public class SSLInterceptor extends AbstractInterceptor {
private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(AjaxInterceptor.class);
private String httpsPort;
private String httpPort;
private boolean useAnnotations = true;
/**
* Defaults for HTTP and HTTPS ports. Can be overridden in as a interceptor parm in config file.
*/
final static int HTTP_PORT = 8080;
final static int HTTPS_PORT = 8443;
final static String HTTP_GET = "GET";
final static String HTTP_POST = "POST";
final static String SCHEME_HTTP = "http";
final static String SCHEME_HTTPS = "https";
/** Creates a new instance of SSLInterceptor */
public SSLInterceptor() {
super();
logger.info ("Intializing SSLInterceptor");
}
/**
* Redirect to SSL or non-SSL version of page as indicated by the presence (or absence) of the
* @Secure annotation on the action class.
*/
public String intercept(ActionInvocation invocation) throws Exception {
// initialize request and response
final ActionContext context = invocation.getInvocationContext ();
final HttpServletRequest request =
(HttpServletRequest) context.get(StrutsStatics.HTTP_REQUEST);
final HttpServletResponse response =
(HttpServletResponse) context.get(StrutsStatics.HTTP_RESPONSE);
// add bypass for file uploads
if (isFileUploadRequest(request)) {
return invocation.invoke();
}
//add by pass for session tokens
String queryString = RequestUtil.buildQueryString(request);
if (queryString != null && (queryString.toLowerCase().indexOf("&token=") != -1 || queryString.toLowerCase().indexOf("token=") != -1)) {
return invocation.invoke();
}
// check scheme
String scheme = request.getScheme().toLowerCase();
// check method
String method = request.getMethod().toUpperCase();
// if useAnnotations is true check for the annotaion marker in the class level or method level
// else make every request secure.
// If the action class/method uses the Secured marker annotation, then see if we need to
// redirect to the SSL protected version of this page
Object action = invocation.getAction();
Method method2 = getActionMethod(action.getClass(), invocation.getProxy().getMethod());
boolean flg=false;
if (request.getSession().getAttribute("requestUri") != null && request.getRequestURI().equals((String)request.getSession().getAttribute("requestUri"))) {
//we are coming for 2nd time
request.getSession().setAttribute("requestUri", null);
flg=true;
} else {
request.getSession().setAttribute("requestUri", request.getRequestURI());
}
if (request.getSession().getAttribute("switchToHttp") != null) {
request.getSession().setAttribute("switchToHttp", null);
return invocation.invoke();
}
// If the protocols are the same allow to pass without a redirect
// NOTE: if statements are seperated but doesn't need to be
// think it might be easier to read as separate if else statements
// If https
// Else if http
if ((action.getClass().isAnnotationPresent(Secured.class) ||
method2.isAnnotationPresent(Secured.class) &&
referer.toLowerCase().startsWith(SCHEME_HTTPS.toLowerCase()))) {
return invocation.invoke();
}
else if (!method2.isAnnotationPresent(Secured.class) &&
referer.toLowerCase().startsWith(SCHEME_HTTP.toLowerCase() + "://")) {
return invocation.invoke();
}
if ( flg ) {
//we are here 2nd time with http scheme
if ( (HTTP_GET.equals(method) || HTTP_POST.equals(method)) && SCHEME_HTTP.equals(scheme)){
if ((!isUseAnnotations() || action.getClass().isAnnotationPresent(Secured.class) || method2.isAnnotationPresent(Secured.class) )) {
return invocation.invoke();
}
// initialize https port
int httpsPort = getHttpPort() == null? HTTP_PORT : Integer.parseInt(getHttpPort());
URI uri = new URI(SCHEME_HTTP, null, request.getServerName(),
httpsPort, response.encodeRedirectURL(request.getRequestURI()),
queryString, null);
logger.info("Going to SSL mode , redirecting to " + uri.toString());
response.sendRedirect(uri.toString());
return null;
}
} else if (!isUseAnnotations() || action.getClass().isAnnotationPresent(Secured.class) || method2.isAnnotationPresent(Secured.class) ){
if ( (HTTP_GET.equals(method) || HTTP_POST.equals(method)) && SCHEME_HTTP.equals(scheme)){
// initialize https port
int httpsPort = getHttpsPort() == null? HTTPS_PORT : Integer.parseInt(getHttpsPort());
URI uri = new URI(SCHEME_HTTPS, null, request.getServerName(),
httpsPort, response.encodeRedirectURL(request.getRequestURI()),
queryString, null);
logger.info("Going to SSL mode, redirecting to " + uri.toString());
response.sendRedirect(uri.toString());
return null;
}
} else{
if ((HTTP_GET.equals(method) || HTTP_POST.equals(method)) && SCHEME_HTTP.equals(scheme)){//used to be SCHEME_HTTPS
// initialize http port
int httpPort = getHttpPort() == null? HTTP_PORT : Integer.parseInt(getHttpPort());
URI uri = new URI(SCHEME_HTTP, null, request.getServerName(),
httpPort, response.encodeRedirectURL(request.getRequestURI()),
queryString, null);
logger.info("Going to non-SSL mode, redirecting to " + uri.toString());
request.getSession().setAttribute("switchToHttp", "true");
response.sendRedirect(uri.toString());
return null;
}
}
return invocation.invoke();
}
// NTS
private boolean isFileUploadRequest(HttpServletRequest request) {
return request.getContentType() != null && request.getContentType().toLowerCase().startsWith("multipart/form-data")
&& request.getMethod() != null && request.getMethod().equalsIgnoreCase("POST");
}
// FIXME: This is copied from DefaultActionInvocation but should be exposed through the interface
protected Method getActionMethod(Class actionClass, String methodName) throws NoSuchMethodException {
Method method;
try {
method = actionClass.getMethod(methodName, new Class[0]);
} catch (NoSuchMethodException e) {
// hmm -- OK, try doXxx instead
try {
String altMethodName = "do" + methodName.substring(0, 1).toUpperCase() + methodName.substring(1);
method = actionClass.getMethod(altMethodName, new Class[0]);
} catch (NoSuchMethodException e1) {
// throw the original one
throw e;
}
}
return method;
}
public String getHttpsPort() {
return httpsPort;
}
@Inject(value="struts2.sslplugin.httpsPort",required = false)
public void setHttpsPort(String httpsPort) {
this.httpsPort = httpsPort;
}
public String getHttpPort() {
return httpPort;
}
@Inject(value = "struts2.sslplugin.httpPort", required = false)
public void setHttpPort(String httpPort) {
this.httpPort = httpPort;
}
public boolean isUseAnnotations() {
return useAnnotations;
}
public void setUseAnnotations(boolean useAnnotations) {
this.useAnnotations = useAnnotations;
}
@Inject(value = "struts2.sslplugin.annotations", required = false)
public void setAnnotations(String annotations) {
if (annotations==null) {
annotations = "true";
}
this.useAnnotations = new Boolean(annotations).booleanValue();
}
}
No comments:
Post a Comment