Revision: 10139
Author: jlaba...@google.com
Date: Wed May 4 11:30:38 2011
Log: Adds user authentication to MobileWebApp. Tasks are now specific
to each user. Authentication is done using a Filter, which was copied
almost verbatim from the expenses sample. If a user is not logged in, they
are forwarded to the login page, then redirected back to their last place
in the app. If a user tries to access a task that they do not own, an
error messge says that the task cannot be found.
You can view a demo at http://jlabanca-testing.appspot.com
This change also replaces the auto generated datastore index file with a
manual datastore index file. There aren't any indexes yet, but we may add
them eventually, and using an auto-generated file is asking for trouble
because its easy enough to miss a possible index.
Review at http://gwt-code-reviews.appspot.com/1432801
Review by: rj...@google.com
http://code.google.com/p/google-web-toolkit/source/detail?r=10139
Added:
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/gaerequest
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/gaerequest/GaeRequest.gwt.xml
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/gaerequest/client
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/gaerequest/client/GaeAuthRequestTransport.java
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/gaerequest/client/GaeAuthenticationFailureEvent.java
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/gaerequest/client/ReloadOnAuthenticationFailure.java
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/gaerequest/server
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/gaerequest/server/GaeAuthFilter.java
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/gaerequest/shared
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/gaerequest/shared/GaeHelper.java
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/server/domain/UserServiceWrapper.java
/trunk/samples/mobilewebapp/war/WEB-INF/datastore-indexes.xml
Modified:
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/MobileWebApp.gwt.xml
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/ClientFactoryImpl.java
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/MobileWebApp.java
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/server/domain/Task.java
/trunk/samples/mobilewebapp/war/WEB-INF/web.xml
=======================================
--- /dev/null
+++
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/gaerequest/GaeRequest.gwt.xml
Wed May 4 11:30:38 2011
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit
0.0.999//EN" "http://google-web-toolkit.googlecode.com/svn/tags/0.0.999/distro-source/core/src/gwt-module.dtd">
+<module>
+ <inherits name='com.google.web.bindery.requestfactory.RequestFactory'/>
+
+ <source path='client'/>
+ <source path='shared'/>
+</module>
=======================================
--- /dev/null
+++
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/gaerequest/client/GaeAuthRequestTransport.java
Wed May 4 11:30:38 2011
@@ -0,0 +1,76 @@
+/*
+ * 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.sample.gaerequest.client;
+
+import com.google.gwt.event.shared.EventBus;
+import com.google.gwt.http.client.Request;
+import com.google.gwt.http.client.RequestCallback;
+import com.google.gwt.http.client.Response;
+import com.google.gwt.sample.gaerequest.shared.GaeHelper;
+import com.google.gwt.user.client.Window;
+import
com.google.web.bindery.requestfactory.gwt.client.DefaultRequestTransport;
+import com.google.web.bindery.requestfactory.shared.ServerFailure;
+
+/**
+ * Extends DefaultRequestTransport to handle the authentication failures
+ * reported by {@link
com.google.gwt.sample.gaerequest.server.GaeAuthFilter}.
+ */
+public class GaeAuthRequestTransport extends DefaultRequestTransport {
+ private final EventBus eventBus;
+
+ public GaeAuthRequestTransport(EventBus eventBus) {
+ this.eventBus = eventBus;
+ }
+
+ @Override
+ protected RequestCallback createRequestCallback(final TransportReceiver
receiver) {
+ final RequestCallback superCallback =
super.createRequestCallback(receiver);
+
+ return new RequestCallback() {
+ public void onError(Request request, Throwable exception) {
+ superCallback.onError(request, exception);
+ }
+
+ public void onResponseReceived(Request request, Response response) {
+ /*
+ * The GaeAuthFailure filter responds with
Response.SC_UNAUTHORIZED and
+ * adds a "login" url header if the user is not logged in. When we
+ * receive that combo, post an event so that the app can handle
things
+ * as it sees fit.
+ */
+
+ if (Response.SC_UNAUTHORIZED == response.getStatusCode()) {
+ String loginUrl = response.getHeader("login");
+ if (loginUrl != null) {
+ // Replace the redirect url placeholder with the current url.
+ loginUrl = loginUrl.replace(GaeHelper.REDIRECT_URL_TOKEN,
Window.Location.getHref());
+
+ /*
+ * Hand the receiver a non-fatal callback, so that *
+ * com.google.web.bindery.requestfactory.shared.Receiver will
not
+ * post a runtime exception.
+ */
+ receiver
+ .onTransportFailure(new ServerFailure("Unauthenticated
user", null, null, false));
+ eventBus.fireEvent(new
GaeAuthenticationFailureEvent(loginUrl));
+ return;
+ }
+ }
+ superCallback.onResponseReceived(request, response);
+ }
+ };
+ }
+}
=======================================
--- /dev/null
+++
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/gaerequest/client/GaeAuthenticationFailureEvent.java
Wed May 4 11:30:38 2011
@@ -0,0 +1,84 @@
+/*
+ * 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.sample.gaerequest.client;
+
+import com.google.gwt.event.shared.EventBus;
+import com.google.gwt.event.shared.EventHandler;
+import com.google.gwt.event.shared.GwtEvent;
+import com.google.gwt.event.shared.HandlerRegistration;
+
+/**
+ * An event posted when an authentication failure is detected.
+ */
+public class GaeAuthenticationFailureEvent extends
GwtEvent<GaeAuthenticationFailureEvent.Handler> {
+
+ /**
+ * Implemented by handlers of this type of event.
+ */
+ public interface Handler extends EventHandler {
+ /**
+ * Called when a {@link GaeAuthenticationFailureEvent} is fired.
+ *
+ * @param requestEvent a {@link GaeAuthenticationFailureEvent} instance
+ */
+ void onAuthFailure(GaeAuthenticationFailureEvent requestEvent);
+ }
+
+ private static final Type<Handler> TYPE = new Type<Handler>();
+
+ /**
+ * Register a {@link GaeAuthenticationFailureEvent.Handler} on an
+ * {@link EventBus}.
+ *
+ * @param eventBus the {@link EventBus}
+ * @param handler a {@link GaeAuthenticationFailureEvent.Handler}
+ * @return a {@link HandlerRegistration} instance
+ */
+ public static HandlerRegistration register(EventBus eventBus,
+ GaeAuthenticationFailureEvent.Handler handler) {
+ return eventBus.addHandler(TYPE, handler);
+ }
+
+ private final String loginUrl;
+
+ /**
+ * Constructs a new @{link RequestEvent}.
+ *
+ * @param loginUrl the url used to login
+ */
+ public GaeAuthenticationFailureEvent(String loginUrl) {
+ this.loginUrl = loginUrl;
+ }
+
+ @Override
+ public GwtEvent.Type<Handler> getAssociatedType() {
+ return TYPE;
+ }
+
+ /**
+ * Returns the URL the user can visit to reauthenticate.
+ *
+ * @return a {@link com.google.gwt.http.client.Response} instance
+ */
+ public String getLoginUrl() {
+ return loginUrl;
+ }
+
+ @Override
+ protected void dispatch(Handler handler) {
+ handler.onAuthFailure(this);
+ }
+}
=======================================
--- /dev/null
+++
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/gaerequest/client/ReloadOnAuthenticationFailure.java
Wed May 4 11:30:38 2011
@@ -0,0 +1,35 @@
+/*
+ * 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.sample.gaerequest.client;
+
+import com.google.gwt.event.shared.EventBus;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.user.client.Window.Location;
+
+/**
+ * A minimal auth failure handler which takes the user a login page.
+ */
+public class ReloadOnAuthenticationFailure implements
GaeAuthenticationFailureEvent.Handler {
+
+ public void onAuthFailure(GaeAuthenticationFailureEvent requestEvent) {
+ Location.replace(requestEvent.getLoginUrl());
+ }
+
+ public HandlerRegistration register(EventBus eventBus) {
+ return GaeAuthenticationFailureEvent.register(eventBus, this);
+ }
+}
=======================================
--- /dev/null
+++
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/gaerequest/server/GaeAuthFilter.java
Wed May 4 11:30:38 2011
@@ -0,0 +1,58 @@
+/*
+ * 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.sample.gaerequest.server;
+
+import com.google.appengine.api.users.UserService;
+import com.google.appengine.api.users.UserServiceFactory;
+import com.google.gwt.sample.gaerequest.shared.GaeHelper;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * A servlet filter that handles basic GAE user authentication.
+ */
+public class GaeAuthFilter implements Filter {
+
+ public void destroy() {
+ }
+
+ public void doFilter(ServletRequest servletRequest, ServletResponse
servletResponse,
+ FilterChain filterChain) throws IOException, ServletException {
+ UserService userService = UserServiceFactory.getUserService();
+ HttpServletRequest request = (HttpServletRequest) servletRequest;
+ HttpServletResponse response = (HttpServletResponse) servletResponse;
+
+ if (!userService.isUserLoggedIn()) {
+ response.setHeader("login",
userService.createLoginURL(GaeHelper.REDIRECT_URL_TOKEN));
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+ return;
+ }
+
+ filterChain.doFilter(request, response);
+ }
+
+ public void init(FilterConfig config) {
+ }
+}
=======================================
--- /dev/null
+++
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/gaerequest/shared/GaeHelper.java
Wed May 4 11:30:38 2011
@@ -0,0 +1,29 @@
+/*
+ * 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.sample.gaerequest.shared;
+
+/**
+ * Helper class for sharing values on the server and client.
+ */
+public interface GaeHelper {
+
+ /**
+ * The placeholder token added to the login URL. The client replaces the
token
+ * with the current href, which only the client knows.
+ */
+ /* Prefixed with http:// to ensure that GAE doesn't automatically prefix
it. */
+ String REDIRECT_URL_TOKEN = "http%3A%2F%2FREDIRECTURL";
+}
=======================================
--- /dev/null
+++
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/server/domain/UserServiceWrapper.java
Wed May 4 11:30:38 2011
@@ -0,0 +1,61 @@
+/*
+ * 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.sample.mobilewebapp.server.domain;
+
+import com.google.appengine.api.users.User;
+import com.google.appengine.api.users.UserServiceFactory;
+
+/**
+ * Wrapper around the {@link com.google.appengine.api.users.UserService}
GAE
+ * api.
+ */
+public class UserServiceWrapper {
+
+ public static UserServiceWrapper instance = new UserServiceWrapper();
+
+ public static UserServiceWrapper get() {
+ return instance;
+ }
+
+ private UserServiceWrapper() {
+ }
+
+ /**
+ * Get the current user.
+ * {@link com.google.gwt.sample.gaerequest.server.GaeAuthFilter} should
ensure
+ * that the user is logged in, but we take precautions here as well.
+ *
+ * @return the current user
+ * @throws RuntimeException if the user is not logged in
+ */
+ public User getCurrentUser() {
+ User currentUser =
UserServiceFactory.getUserService().getCurrentUser();
+ if (currentUser == null) {
+ throw new RuntimeException("User not logged in");
+ }
+ return currentUser;
+ }
+
+ /**
+ * Get the unique ID of the current user.
+ *
+ * @return a unique ID
+ * @throws RuntimeException if the user is not logged in
+ */
+ public String getCurrentUserId() {
+ return getCurrentUser().getUserId();
+ }
+}
=======================================
--- /dev/null
+++ /trunk/samples/mobilewebapp/war/WEB-INF/datastore-indexes.xml Wed May
4 11:30:38 2011
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<datastore-indexes
+ autoGenerate="false">
+
+</datastore-indexes>
+
=======================================
---
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/MobileWebApp.gwt.xml
Wed May 4 09:12:17 2011
+++
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/MobileWebApp.gwt.xml
Wed May 4 11:30:38 2011
@@ -8,6 +8,7 @@
<inherits name='com.google.gwt.editor.Editor'/>
<inherits name='com.google.gwt.sample.mobilewebapp.FormFactor'/>
<inherits name='com.google.web.bindery.requestfactory.RequestFactory'/>
+ <inherits name='com.google.gwt.sample.gaerequest.GaeRequest'/>
<!-- Specify the app entry point class. -->
<entry-point
class='com.google.gwt.sample.mobilewebapp.client.MobileWebApp'/>
=======================================
---
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/ClientFactoryImpl.java
Tue May 3 10:43:13 2011
+++
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/ClientFactoryImpl.java
Wed May 4 11:30:38 2011
@@ -19,14 +19,15 @@
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.place.shared.PlaceController;
-import
com.google.web.bindery.requestfactory.gwt.client.DefaultRequestTransport;
-import com.google.gwt.storage.client.Storage;
-import com.google.gwt.user.client.Window;
+import com.google.gwt.sample.gaerequest.client.GaeAuthRequestTransport;
import com.google.gwt.sample.mobilewebapp.client.activity.TaskEditView;
import com.google.gwt.sample.mobilewebapp.client.activity.TaskListView;
import
com.google.gwt.sample.mobilewebapp.client.desktop.DesktopTaskEditView;
import
com.google.gwt.sample.mobilewebapp.client.desktop.DesktopTaskListView;
import
com.google.gwt.sample.mobilewebapp.client.desktop.MobileWebAppShellDesktop;
+import com.google.gwt.storage.client.Storage;
+import com.google.gwt.user.client.Window;
+import com.google.web.bindery.requestfactory.shared.RequestTransport;
/**
* Default implementation of {@link ClientFactory}. Used by desktop
version.
@@ -47,7 +48,7 @@
private TaskListView taskListView;
public ClientFactoryImpl() {
- DefaultRequestTransport requestTransport = new
DefaultRequestTransport();
+ RequestTransport requestTransport = new
GaeAuthRequestTransport(eventBus);
requestFactory = GWT.create(MobileWebAppRequestFactory.class);
requestFactory.initialize(eventBus, requestTransport);
=======================================
---
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/MobileWebApp.java
Tue May 3 10:43:13 2011
+++
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/client/MobileWebApp.java
Wed May 4 11:30:38 2011
@@ -26,6 +26,7 @@
import com.google.gwt.place.shared.PlaceHistoryHandler;
import com.google.gwt.place.shared.PlaceHistoryHandler.DefaultHistorian;
import com.google.gwt.place.shared.PlaceHistoryHandler.Historian;
+import
com.google.gwt.sample.gaerequest.client.ReloadOnAuthenticationFailure;
import
com.google.gwt.sample.mobilewebapp.client.activity.AppActivityMapper;
import
com.google.gwt.sample.mobilewebapp.client.place.AppPlaceHistoryMapper;
import com.google.gwt.sample.mobilewebapp.client.place.TaskListPlace;
@@ -53,6 +54,9 @@
EventBus eventBus = clientFactory.getEventBus();
PlaceController placeController = clientFactory.getPlaceController();
+ // Check for Authentication failures or mismatches
+ new ReloadOnAuthenticationFailure().register(eventBus);
+
/*
* Add the main application shell to the RootLayoutPanel. The shell
includes
* the header bar at the top and a content area.
=======================================
---
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/server/domain/Task.java
Tue May 3 10:43:13 2011
+++
/trunk/samples/mobilewebapp/src/main/com/google/gwt/sample/mobilewebapp/server/domain/Task.java
Wed May 4 11:30:38 2011
@@ -36,13 +36,14 @@
public class Task {
/**
- * Find all tasks.
+ * Find all tasks for the current user.
*/
@SuppressWarnings("unchecked")
public static List<Task> findAllTasks() {
EntityManager em = entityManager();
try {
- Query query = em.createQuery("select o from Task o");
+ Query query = em.createQuery("select o from Task o where
o.userId=:userId");
+ query.setParameter("userId",
UserServiceWrapper.get().getCurrentUserId());
List<Task> list = query.getResultList();
/*
@@ -67,7 +68,7 @@
}
/**
- * Find a {@link Task} by id.
+ * Find a {@link Task} by id for the current user.
*
* @param id the {@link Task} id
* @return the associated {@link Task}, or null if not found
@@ -76,10 +77,14 @@
if (id == null) {
return null;
}
+
EntityManager em = entityManager();
try {
Task task = em.find(Task.class, id);
- return task;
+ if (task != null &&
UserServiceWrapper.get().getCurrentUserId().equals(task.userId)) {
+ return task;
+ }
+ return null;
} finally {
em.close();
}
@@ -135,6 +140,11 @@
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
+ /**
+ * The unique ID of the user who owns this task.
+ */
+ private String userId;
+
@Version
@Column(name = "version")
private Integer version;
@@ -187,7 +197,16 @@
public void persist() {
EntityManager em = entityManager();
try {
- em.persist(this);
+ // Set the user id if this is a new task.
+ String curUserId = UserServiceWrapper.get().getCurrentUserId();
+ if (userId == null) {
+ userId = curUserId;
+ }
+
+ // Verify the current user owns the task before updating it.
+ if (curUserId.equals(userId)) {
+ em.persist(this);
+ }
} finally {
em.close();
}
@@ -200,7 +219,11 @@
EntityManager em = entityManager();
try {
Task task = em.find(Task.class, this.id);
- em.remove(task);
+
+ // Verify the current user owns the task before removing it.
+ if (UserServiceWrapper.get().getCurrentUserId().equals(task.userId))
{
+ em.remove(task);
+ }
} finally {
em.close();
}
=======================================
--- /trunk/samples/mobilewebapp/war/WEB-INF/web.xml Wed May 4 09:12:17 2011
+++ /trunk/samples/mobilewebapp/war/WEB-INF/web.xml Wed May 4 11:30:38 2011
@@ -5,6 +5,24 @@
<web-app>
+ <!--
+ Require login. We only require login for the MobileWebApp.html page
(instead of *.html) because
+ we do not want to require login for the compiled GWT javascript files,
which also end in .html.
+ -->
+ <security-constraint>
+ <display-name>
+ Redirect to the login page if needed before showing
+ the host html page.
+ </display-name>
+ <web-resource-collection>
+ <web-resource-name>Login required</web-resource-name>
+ <url-pattern>/MobileWebApp.html</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>*</role-name>
+ </auth-constraint>
+ </security-constraint>
+
<!-- RequestFactory -->
<servlet>
<servlet-name>requestFactoryServlet</servlet-name>
@@ -15,7 +33,20 @@
<servlet-name>requestFactoryServlet</servlet-name>
<url-pattern>/gwtRequest</url-pattern>
</servlet-mapping>
-
+
+ <filter>
+ <filter-name>GaeAuthFilter</filter-name>
+ <description>
+ This filter demonstrates making GAE authentication
+ services visible to a RequestFactory client.
+ </description>
+
<filter-class>com.google.gwt.sample.gaerequest.server.GaeAuthFilter</filter-class>
+ </filter>
+ <filter-mapping>
+ <filter-name>GaeAuthFilter</filter-name>
+ <url-pattern>/gwtRequest/*</url-pattern>
+ </filter-mapping>
+
<!-- Default page to serve -->
<welcome-file-list>
<welcome-file>MobileWebApp.html</welcome-file>
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors