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