Remeber-me not working for me in autoLogin mode
cosmo Aug 4, 2011 4:31 PMHello folks,
I have an application that requires SEAM's remember me functionality(autoLogin), but unfortunately I can not get it to work.
I am pretty sure the error I am making must be a minor detail I passed because all the steps in the documentation seem to be really clear.
Anyways, thanks in advance for any time you spent in this post.
1 Behavior expected / watched
As cookies are being stored in my browser, I would expect that after I close the browser and re-open it again, I would be transparently logged in.
Instead, I am taken to the log in page as if no remember me(autoLogin) functionality was enabled.
2 Relevant source code
components.xml
<?xml version="1.0" encoding="UTF-8"?>
<components xmlns="http://jboss.com/products/seam/components"
xmlns:core="http://jboss.com/products/seam/core"
xmlns:mail="http://jboss.com/products/seam/mail"
xmlns:persistence="http://jboss.com/products/seam/persistence"
xmlns:security="http://jboss.com/products/seam/security"
xmlns:web="http://jboss.com/products/seam/web"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jboss.com/products/seam/core http://jboss.com/products/seam/core-2.2.xsd http://jboss.com/products/seam/persistence http://jboss.com/products/seam/persistence-2.2.xsd http://jboss.com/products/seam/drools http://jboss.com/products/seam/drools-2.2.xsd http://jboss.com/products/seam/bpm http://jboss.com/products/seam/bpm-2.2.xsd http://jboss.com/products/seam/security http://jboss.com/products/seam/security-2.2.xsd http://jboss.com/products/seam/mail http://jboss.com/products/seam/mail-2.2.xsd http://jboss.com/products/seam/web http://jboss.com/products/seam/web-2.2.xsd http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.2.xsd">
<core:init debug="@debug@" jndi-pattern="@jndiPattern@" />
<core:manager concurrent-request-timeout="500"
conversation-id-parameter="cid" conversation-timeout="120000" parent-conversation-id-parameter="pid"/>
<!-- Make sure this URL pattern is the same as that used by the Faces Servlet -->
<web:hot-deploy-filter url-pattern="*.seam"/>
<persistence:managed-persistence-context auto-create="true"
name="entityManagerR" persistence-unit-jndi-name="java:/wmsEntityManagerFactory"/>
<persistence:managed-persistence-context auto-create="true"
name="entityManagerRBue" persistence-unit-jndi-name="java:/wmsRBueEntityManagerFactory"/>
<persistence:managed-persistence-context auto-create="true"
name="entityManagerRW" persistence-unit-jndi-name="java:/wmsRWEntityManagerFactory"/>
<security:jpa-identity-store
role-class="my.package.model.Role" user-class="my.package.model.User"/>
<security:jpa-token-store token-class="my.package.model.AuthenticationToken"/>
<security:identity authenticate-method="#{authenticator.authenticate}" remember-me="true"/>
<security:remember-me mode="autoLogin"/>
<event type="org.jboss.seam.security.notLoggedIn">
<action execute="#{redirect.captureCurrentView}"/>
<action execute="#{identity.tryLogin}"/>
</event>
<event type="org.jboss.seam.security.loginSuccessful">
<action execute="#{redirect.returnToCapturedView}"/>
</event>
<factory auto-create="true" name="httpSession" value="#{facesContext.externalContext.request.session}"/>
<factory auto-create="true" name="userIP" value="#{facesContext.externalContext.request.remoteAddr}" />
<factory auto-create="true" name="entityManager" value="#{entityManagerRW}"/>
</components>index.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:s="http://jboss.com/products/seam/taglib"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:rich="http://richfaces.org/rich"
xmlns:a4j="http://richfaces.org/a4j"
template="layout/template.xhtml">
<ui:define name="body">
<s:div id="mainArea">
<s:div styleClass="content_box">
<rich:panel id="loginPanel" styleClass="login-panel" width="300" height="150" >
<f:facet name="header">Login</f:facet>
<h:panelGrid columns="1" columnClasses="login-table-col" style="width: 100%; text-align:center;" >
<h:panelGrid columns="2" columnClasses="login-table-col2, xxx" style="margin-left:auto; margin-right:auto;">
<h:outputText value="User" />
<h:inputText id="usuario" value="#{credentials.username}" style="border: 1px solid rgb(144, 144, 144); height: 19px; width: 155px;" autocomplete="off"/>
<h:outputText value="Password" />
<h:inputSecret id="password" value="#{credentials.password}" style="border: 1px solid rgb(144, 144, 144); height: 19px; width: 155px;" autocomplete="off"/>
<h:outputText value="Remember me" />
<h:selectBooleanCheckbox value="#{rememberMe.enabled}" />
</h:panelGrid>
<h:commandButton style="login" action="#{loginForm.login}" value="Login" />
</h:panelGrid>
</rich:panel>
</s:div>
</s:div>
</ui:define>
</ui:composition>LoginForm.java
@Name("loginForm")
@Scope(ScopeType.PAGE)
public class LoginForm {
@In ReCaptchaProvider reCaptcha;
@In Identity identity;
@In BruteForceDetector bruteForceDetector;
@In String userIP;
public String login(){
if (bruteForceDetector.needsCaptchaOnLogin(userIP)){
if (reCaptcha.isCaptchaValid()){
Contexts.getEventContext().set("comesFromCaptchaLogin", "true");
return identity.login();
}else{
StatusMessages.instance().addFromResourceBundle("captcha.invalid");
return null;
}
}else{
return identity.login();
}
}
}User.java
@Entity
@Table(name="puser")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String password;
private String name;
private String email;
private String client;
private Set<Role> userRoles;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@UserPassword
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@UserPrincipal
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getClient() {
return client;
}
public void setClient(String client) {
this.client = client;
}
public void removeRole(Role role) {
getUserRoles().remove(role);
role.getRoleUsers().remove(this);
}
public void addRole(Role role) {
getUserRoles().add(role);
role.getRoleUsers().add(this);
}
@UserRoles
@ManyToMany(targetEntity = Role.class,cascade = {CascadeType.PERSIST,CascadeType.MERGE})
@JoinTable(name = "ex_user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
public Set<Role> getUserRoles() {
if (userRoles == null) {
userRoles = new HashSet<Role> ();
}
return userRoles;
}
public void setUserRoles(Set<Role> userRoles) {
this.userRoles = userRoles;
}
}3 Some relevant facts
- Manual login is working fine
- No exceptions are being thrown nor messages in StatusMessage when autoLogin fails
- The token is being saved in DB
- I can see the db query each time I ask for a page that a user needs to be logged in order to see, but instead of auto login me, it takes me to login page
- I can see both cookies in my browser(org.jboss.seam.security.authtoken and org.jboss.seam.security.username) with values filled in even after browser close-open
- Username-only mode is correctly working
4 Enviroment
- SEAM 2.2.0 GA
- JBoss 5.1.0 GA
- Postgre 8.4.7
- Open JDK 1.6.0.26
- Ubuntu 32 bit 10.10
- Firefox 3.6.18/Chrome 12.0.742.124