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