RequestFactory Security/Authentication

1,272 views
Skip to first unread message

Max E.

unread,
Nov 9, 2010, 2:16:49 PM11/9/10
to Google Web Toolkit
Hello,

I'm having problems to understand how User Authentication works with
the RequestFactory.
I do understand the documentation and the expenses example.

How is it possible to implement Authentication/ How do users login?
How can Users only view the Entities they are allowed to see.
How can the Server verify that they can only change/persist entities
they are allowed to change?

I did not find any tutorial or documentation about this. The only
thing I found was UserInformation and RequestSecurityProvider in GWT.

Can somebody explain this?

Jack

unread,
Nov 10, 2010, 11:57:34 AM11/10/10
to Google Web Toolkit
Everytime a request is made the RequestFactoryServlet loads an
implementation of UserInformation and calls boolean isUserLoggedIn().
If you do not provide a custom UserInformation implementation a
SimpleUserInformationImpl will be choosen which always returns true
for isUserLoggedIn().

To define a custom UserInformation implementation you need to add to
your web.xml something like this:

<servlet>
<servlet-name>requestFactoryServlet</servlet-name>
<servlet-
class>com.google.gwt.requestfactory.server.RequestFactoryServlet</
servlet-class>
<init-param>
<param-name>userInfoClass</param-name>
<param-value>your.example.YourUserInformationImpl</param-value>
</init-param>
</servlet>

With your own UserInformation implementation you can check if an user
is logged in. Inside the isUserLoggedIn() method you can access the
HttpServletRequest object via

HttpServletRequest request =
RequestFactoryServlet.getThreadLocalRequest();

Now you should have anything you need to authenticate the request
(request cookies, request headers, request session).

To do the actual login and logout of an user I would use a normal GWT
RemoteService with two methods

String login(String user, String password)
void logout(String authtoken)

Patrick Hilsbos

unread,
Nov 12, 2010, 8:32:27 AM11/12/10
to google-we...@googlegroups.com
Hi,
could you get a bit more in detail, how to implement the auth - e.g. where to store the authcode?
Do i have to create a session on my own...?

I already went through a couple of projects dealing with spring security / acegi.

Thanks !!!


--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To post to this group, send email to google-we...@googlegroups.com.
To unsubscribe from this group, send email to google-web-tool...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-web-toolkit?hl=en.


Ramon Buckland

unread,
Nov 24, 2010, 11:13:26 AM11/24/10
to Google Web Toolkit
Hi Patrick,

I just finished (10 mins ago) implementing my Spring Security service
over the top of the Requestfactory.

I am sure there are some holes (not security ones, just stuff I have
missed) but here is what I did.
I have a user entity (that represents the user). this entity has the
username, and the password.

@Entity
@Configurable
public class IsuproUser {

private String username;

private String password;

@OneToOne
private Person person;

// clear or sha256
private String passwordEncoding;

private boolean enabled;
}

/* and example table insert for a user then looks like
INSERT INTO isupro_user (password, username,person, enabled,
password_encoding) VALUES
('5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8','rbuckland',
1, 1, 'sha256')
sha256 value is 'password'.

echo -n password | sha256sum

*/


I have a fairly clean META-INF/spring/applicationContext-security.xml
file.

<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd">

<!-- HTTP security configurations -->
<http auto-config="true" use-expressions="true">
<form-login login-processing-url="/resources/
j_spring_security_check"
login-page="/login.jspx"
authentication-failure-url="/login.jspx?
login_error=t" />
<logout logout-url="/resources/j_spring_security_logout" />

<!-- Configure these elements to secure URIs in your application --
>
<intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')" /
>
<intercept-url pattern="/gwtRequest/**"
access="isAuthenticated()" />
<intercept-url pattern="/isupro.jsp" access="isAuthenticated()" />
<intercept-url pattern="/**" access="permitAll" />

</http>

<beans:bean
class="org.springframework.security.authentication.encoding.ShaPasswordEncoder"
id="passwordEncoder">
<beans:constructor-arg value="256" />
</beans:bean>

<beans:bean id="myUserDetailsService"
class="isupro.security.IsuproUserDetailsService" />

<!-- Configure Authentication mechanism -->
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="myUserDetailsService">
<password-encoder ref="passwordEncoder" />
</authentication-provider>
</authentication-manager>

</beans:beans>


So I have (hopefully) secured the app, on the isupro.jsp (this is the
GWT bootstrap).

I have a UserDetails class. Which is just a minor extension on the
spring one (seems there is some depecation for this "User" class.. but
I moved on :-) worry about that later ).

public class IsuproUserDetails extends User {

private IsuproUser isuproUser;

private static final long serialVersionUID = 1L;

@SuppressWarnings("deprecation")
public IsuproUserDetails(IsuproUser isuproUser) {
super(isuproUser.getUsername(), isuproUser.getPassword(),
isuproUser.getEnabled(),true, true, true, getAuthorities(false));
this.setIsuproUser(isuproUser);
}

// threading issue here .. change
private static GrantedAuthority[] getAuthorities(boolean isAdmin)
{
List<GrantedAuthority> authList = new
ArrayList<GrantedAuthority>(2);
authList.add(new GrantedAuthorityImpl("ROLE_USER"));
if (isAdmin) {
authList.add(new GrantedAuthorityImpl("ROLE_ADMIN"));
}
return authList.toArray(new GrantedAuthority[] {});
}

public void setIsuproUser(IsuproUser isuproUser) {
this.isuproUser = isuproUser;
}

public IsuproUser getIsuproUser() {
return isuproUser;
}

}

Now we have two more classes to care about. first, the one that
SpringSecurity needs, the UserDetails service. I use JPA (it was an
app based off ROO (side note: I find ROO cumbersome! :-/ )


public class IsuproUserDetailsService implements UserDetailsService {

@Override
public UserDetails loadUserByUsername(String username) throws
UsernameNotFoundException, DataAccessException {
IsuproUser isuproUser =
IsuproUser.findUserByUsername(username);
if (isuproUser != null) {
return new IsuproUserDetails(isuproUser);
} else {
throw new UsernameNotFoundException("Username : " +
username + " : was not found");
}
}

}

And then the one that the GWT RequestFactory needs.

public class IsuproUserInformation extends UserInformation {

public IsuproUserInformation(String redirectUrl) {
super(redirectUrl);
}

@Override
public String getEmail() {
return "em...@address.com";
}

@Override
public Long getId() {
if
(SecurityContextHolder.getContext().getAuthentication().isAuthenticated())
{
IsuproUserDetails userdetails = (IsuproUserDetails)
SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return userdetails.getIsuproUser().getId();
} else {
return -1L;
}
}

@Override
public String getLoginUrl() {
return "/login.jspx";
}

@Override
public String getLogoutUrl() {

return "/logout";
}

@Override
public String getName() {
if
(SecurityContextHolder.getContext().getAuthentication().isAuthenticated())
{
IsuproUserDetails userdetails = (IsuproUserDetails)
SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return userdetails.getIsuproUser().getUsername(); // this
could be the name of the getPerson()
} else {
return "Guest";
}

}

@Override
public boolean isUserLoggedIn() {
return
SecurityContextHolder.getContext().getAuthentication().isAuthenticated();
}

@Override
public void setId(Long id) {
// we don't allow setting the ID
}

}


And finally, telling the GWT Requestfactory about this UserInformation
class.

<servlet>
<servlet-name>requestFactory</servlet-name>
<servlet-
class>com.google.gwt.requestfactory.server.RequestFactoryServlet</
servlet-class>
<init-param>
<param-name>userInfoClass</param-name>
<param-value>isupro.security.IsuproUserInformation</param-value>
</init-param>
</servlet>

So now, If i navigate to /isupro.jsp, it pushes me to /login.jspx. I
login with the username/password(database has an encrypted sha256
value of the password and spring does the magic of sha-ing the
password for comparison.

A nice tutorial (for others to read is here).
http://www.packtpub.com/article/spring-security-configuring-secure-passwords


This is what it looks like in GWT to pull that user up. (Straight from
Spring ROO).

/*
* identify the logged in user
*/
Receiver<UserInformationProxy> receiver = new
Receiver<UserInformationProxy>() {
public void onSuccess(UserInformationProxy
userInformationProxy) {

shell.getLoginWidget().setUserInformation(userInformationProxy);
}
};

requestFactory.userInformationRequest().getCurrentUserInformation(Window.Location.getHref()).fire(receiver);


That is it.

HTH
Ramon Buckland

On Nov 12, 1:32 pm, Patrick Hilsbos <patrick.hils...@cloudsters.net>
wrote:

Patrick Hilsbos

unread,
Nov 24, 2010, 3:18:58 PM11/24/10
to google-we...@googlegroups.com
Thx a lot...

how does your web.xml look like and where have you put your login.jspx view? src main webapps view ?
i think im missing the controller referred in webmvc.

cheers
patrick

Ramon Buckland

unread,
Nov 24, 2010, 5:08:14 PM11/24/10
to Google Web Toolkit
I do have a dispatcherServlet (serves up other stuff).

My web.xml


<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://
www.w3.org/2001/XMLSchema-instance" version="2.4"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">


<display-name>isupro</display-name>

<description>isupro application</description>


<!-- Enable escaping of form submission contents -->
<context-param>
<param-name>defaultHtmlEscape</param-name>
<param-value>true</param-value>
</context-param>

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:META-INF/spring/applicationContext*.xml</
param-value>
</context-param>

<filter>
<filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
<filter-
class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</
filter-class>
</filter>


<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-
class>org.springframework.web.filter.DelegatingFilterProxy</filter-
class>
</filter>


<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-
class>org.springframework.web.filter.CharacterEncodingFilter</filter-
class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>

<filter>
<filter-name>HttpMethodFilter</filter-name>
<filter-
class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-
class>
</filter>

<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>


<filter-mapping>
<filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
<filter-name>HttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- Creates the Spring Container shared by all Servlets and
Filters -->
<listener>
<listener-
class>org.springframework.web.context.ContextLoaderListener</listener-
class>
</listener>

<!-- Handles Spring requests -->
<servlet>
<servlet-name>isupro</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</
servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/webmvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>



<servlet>
<servlet-name>requestFactory</servlet-name>
<servlet-
class>com.google.gwt.requestfactory.server.RequestFactoryServlet</
servlet-class>
<init-param>
<param-name>userInfoClass</param-name>
<param-value>isupro.security.IsuproUserInformation</param-value>
</init-param>
</servlet>

<servlet>
<servlet-name>remoteLoggerServiceImpl</servlet-name>
<servlet-
class>com.allen_sauer.gwt.log.server.RemoteLoggerServiceImpl</servlet-
class>
</servlet>

<servlet-mapping>
<servlet-name>remoteLoggerServiceImpl</servlet-name>
<url-pattern>/isupro/gwt-log</url-pattern>
</servlet-mapping>


<servlet-mapping>
<servlet-name>isupro</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

<servlet-mapping>
<servlet-name>requestFactory</servlet-name>
<url-pattern>/gwtRequest</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>10</session-timeout>
</session-config>

</web-app>


On Nov 24, 8:18 pm, Patrick Hilsbos <patrick.hils...@cloudsters.net>
wrote:

Patrick Hilsbos

unread,
Nov 24, 2010, 5:16:33 PM11/24/10
to google-we...@googlegroups.com
looks the same over here...

jogin.jspx get me a "not found"...

/login gets me: 

HTTP ERROR: 500

Circular view path [login]: would dispatch back to the current handler URL [/login] again.

very strange - also set up a new project without gwt but having the same problems there
... 

Ramon Buckland

unread,
Nov 24, 2010, 5:20:35 PM11/24/10
to Google Web Toolkit
my login.jspx is just a file in the root (src/main/webapp/login.jspx)

I also saw that circular reference thingo (ignored it and moved the
file out of WEB-INF/views/login.jspx to /login.jspx .. (again , a time
thing, had no time to debug why().

On Nov 24, 10:16 pm, Patrick Hilsbos <patrick.hils...@cloudsters.net>

Patrick Hilsbos

unread,
Nov 24, 2010, 5:43:12 PM11/24/10
to google-we...@googlegroups.com
now i think i am about to have it running...

found that sample project with correct strcture, maybe were able to get wiring out of that project.

Patrick Hilsbos

unread,
Nov 24, 2010, 6:00:36 PM11/24/10
to google-we...@googlegroups.com
now im stuck at that point

HTTP ERROR: 500

javax.servlet.jsp.PageContext.getELContext()Ljavax/el/ELContext;

RequestURI=/login.jspx

Caused by:

java.lang.AbstractMethodError: javax.servlet.jsp.PageContext.getELContext()Ljavax/el/ELContext;

removed all the message stuff, util taglib / panel

will go on tomorrow...

gn8 to all coming from europe :)


On 24.11.2010, at 23:20, Ramon Buckland wrote:

Patrick Hilsbos

unread,
Nov 25, 2010, 1:12:14 PM11/25/10
to google-we...@googlegroups.com
actually i'm only getting xml output; looks kinda strange.


how does your header look like?

---

xmlns:jsp="http://java.sun.com/JSP/Page"><jsp:output
omit-xml-declaration="yes" /> 


---
thx
On 24.11.2010, at 17:13, Ramon Buckland wrote:

Ramon Buckland

unread,
Nov 26, 2010, 6:44:19 AM11/26/10
to Google Web Toolkit
Yes this does happen. So the answer is:

<jsp:output omit-xml-declaration="yes" />

<jsp:directive.page
pageEncoding="ISO-8859-1"
contentType="text/html; ISO-8859-1" />

This intructs the jspx file ( an XML file ) to tell your browser it
has to be rendered as text/html.
Sets the Content-type: header (see firebug to compare the values of
the Response header before and after if you are interested.

r.


On Nov 25, 6:12 pm, Patrick Hilsbos <patrick.hils...@cloudsters.net>
wrote:
Reply all
Reply to author
Forward
0 new messages