All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gwt.user.server.rpc.XsrfTokenServiceServlet Maven / Gradle / Ivy

/*
 * Copyright 2011 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.user.server.rpc;

import com.google.gwt.user.client.rpc.RpcTokenException;
import com.google.gwt.user.client.rpc.XsrfToken;
import com.google.gwt.user.client.rpc.XsrfTokenService;
import com.google.gwt.user.server.Util;
import com.google.gwt.util.tools.shared.Md5Utils;
import com.google.gwt.util.tools.shared.StringUtils;

import javax.servlet.http.Cookie;

/**
 * EXPERIMENTAL and subject to change. Do not use this in production code.
 * 

* *

* RPC service to generate XSRF tokens. *

* Sample use of {@link XsrfTokenService}: * *

    *
  1. Add {@link XsrfTokenServiceServlet} to {@code web.xml}: * *
     * <servlet>
     *   <servlet-name>xsrf</servlet-name>
     *   <servlet-class>
     *     com.google.gwt.user.server.rpc.XsrfTokenServiceServlet
     *   </servlet-class>
     * </servlet>
     * <servlet-mapping>
     *   <servlet-name>xsrf</servlet-name>
     *   <url-pattern>/gwt/xsrf</url-pattern>
     * </servlet-mapping>
     * 
    * *
  2. Specify session cookie name that is used for authentication. MD5 hash of * the session cookie's value will be used as an XSRF token: * *
     * <context-param>
     *   <param-name>gwt.xsrf.session_cookie_name</param-name>
     *   <param-value>JSESSIONID</param-value>
     * </context-param>
     * 
    * *
  3. To enforce XSRF token validation on each method call either mark RPC * interface as XSRF protected using {@link XsrfProtect} annotation or extend * {@link com.google.gwt.user.client.rpc.XsrfProtectedService} instead of * RemoteService. Use {@link NoXsrfProtect} to mark methods as not requiring * XSRF protection: * *
     * public interface MyRpcService extends XsrfProtectedService {
     *   public void doStuff();
     * }
     * 
    * *
  4. Ensure that RPC's servlet implementation extends {@link * XsrfProtectedServiceServlet} instead of {@link RemoteServiceServlet}: * *
     * public class MyRpcServiceServlet extends XsrfProtectedServiceServlet
     *     implements MyRpcService {
     *
     *   public void doStuff() {
     *     // ...
     *   }
     * }
     * 
    * *
  5. Obtain {@link XsrfToken} and set it on the RPC end point: * *
     * XsrfTokenServiceAsync xsrf = (XsrfTokenServiceAsync)GWT.create(XsrfTokenService.class);
     *
     * ((ServiceDefTarget)xsrf).setServiceEntryPoint(GWT.getModuleBaseURL() + "xsrf");
     *
     * xsrf.getNewXsrfToken(new AsyncCallback<XsrfToken>() {
     *   public void onSuccess(XsrfToken result) {
     *     MyRpcServiceAsync rpc = (MyRpcServiceAsync)GWT.create(MyRpcService.class);
     *     ((HasRpcToken) rpc).setRpcToken(result);
     *     // make XSRF protected RPC call
     *     rpc.doStuff(new AsyncCallback<Void>() {
     *       // ...
     *     });
     *
     *   }
     *
     *   public void onFailure(Throwable caught) {
     *     try {
     *       throw caught;
     *     } catch (RpcTokenException e) {
     *       // Can be thrown for several reasons:
     *       //   - duplicate session cookie, which may be a sign of a cookie
     *       //     overwrite attack
     *       //   - XSRF token cannot be generated because session cookie isn't
     *       //     present
     *     } catch (Throwable e) {
     *       // unexpected
     *     }
     * });
     * 
    *
*

* * @see XsrfProtectedServiceServlet * @see XsrfProtect * @see NoXsrfProtect */ public class XsrfTokenServiceServlet extends RemoteServiceServlet implements XsrfTokenService { /** * Session cookie name initialization parameter. */ public static final String COOKIE_NAME_PARAM = "gwt.xsrf.session_cookie_name"; static final String COOKIE_NAME_NOT_SET_ERROR_MSG = "Session cookie name not set! Use '" + COOKIE_NAME_PARAM + "' context-param to specify session cookie name"; /** * Session cookie name. Cookie's value is used to generate XSRF cookie. */ private String sessionCookieName = null; /** * Default constructor. */ public XsrfTokenServiceServlet() { this(null); } /** * Alternative constructor that accepts session cookie name instead of getting * it from {@link javax.servlet.ServletConfig} or {@link * javax.servlet.ServletContext}. */ public XsrfTokenServiceServlet(String sessionCookieName) { this.sessionCookieName = sessionCookieName; } /** * Generates and returns new XSRF token. */ public XsrfToken getNewXsrfToken() { return new XsrfToken(generateTokenValue()); } /** * Servlet initialization. */ @Override public void init() { // do not overwrite values set via constructor if (sessionCookieName == null) { sessionCookieName = getInitParameterValue(COOKIE_NAME_PARAM); } if (sessionCookieName == null) { throw new IllegalStateException(COOKIE_NAME_NOT_SET_ERROR_MSG); } } /** * Generates new XSRF token. * * @return session cookie MD5 hash. */ private String generateTokenValue() { if (sessionCookieName == null) { throw new IllegalStateException(COOKIE_NAME_NOT_SET_ERROR_MSG); } // generate XSRF cookie using session cookie Cookie sessionCookie = Util.getCookie(getThreadLocalRequest(), sessionCookieName, false); if (sessionCookie == null || sessionCookie.getValue() == null || sessionCookie.getValue().length() == 0) { throw new RpcTokenException("Session cookie is not set or empty! " + "Unable to generate XSRF cookie"); } byte[] cookieBytes = sessionCookie.getValue().getBytes(); return StringUtils.toHexString(Md5Utils.getMd5Digest(cookieBytes)); } /** * Retrieves and returns specified initialization parameter first from * {@link ServletConfig} followed by {@link ServletContext}, if former returns * {@code null}. */ private String getInitParameterValue(String name) { String paramValue = null; paramValue = getServletConfig().getInitParameter(name); if (paramValue == null) { paramValue = getServletContext().getInitParameter(name); } return paramValue; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy