It's a common best practice to renew the HTTP session when logging in a user. This will force a new session ID, avoiding session fixation vulnerabilities.
Is there a preferred pattern for implementing this with CDI when @SessionScoped beans are involved? The difficulty is that by invalidating the current HTTP session, you'll then get a different session-scoped bean with the next request, but not until the next request.
For example, assume a session bean for storing user login information:
@Named("sessionbean")
@SessionScoped
public class SessionBean implements Serializable {
private int userId;
private String username;
private List<String> privileges;
// Accessors omitted
}
And another bean for managing the login:
@Named("loginbean")
@ViewScoped
public class LoginBean implements Serializable {
private String username;
private String password;
@Inject private SessionBean session;
@Inject private SessionManager sessionManager;
@Inject private PrivilegeManager privilegeManager;
public String doLogin() {
String destinationUrl;
if (validate(username, password)) {
FacesContext context = FacesContext.getCurrentInstance();
// force renewal of HTTP session
context.getExternalContext().invalidateSession();
// retrieve new session bean ** No longer works with CDI **
Application app = context.getApplication();
session = app.evaluateExpressionGet(context, "#{sessionbean}", SessionBean.class);
session.setUsername(username);
session.setSessionId(sessionManager.createNewSession(username));
session.setPrivileges(privilegeManager.getPrivileges(username));
destinationUrl = createLandingPageUrl();
} else {
destinationUrl = createFailureUrl("Unknown user or password");
}
return destinationUrl;
}
}
With Managed Beans this would retrieve a new SessionBean, but with CDI, the code above would just return the same SessionBean. Any recommendations or clever ideas?