Did*_*jit 6 session jsf cdi jsf-2.3
在用户登录时更新 HTTP 会话是一种常见的最佳实践。这将强制使用新的会话 ID,避免会话固定漏洞。
当涉及@SessionScoped bean 时,是否有使用 CDI 实现此功能的首选模式?困难在于,通过使当前的 HTTP 会话无效,您将在下一个请求中获得一个不同的会话范围的 bean,但直到下一个请求才会如此。
例如,假设一个会话 bean 用于存储用户登录信息:
@Named("sessionbean")
@SessionScoped
public class SessionBean implements Serializable {
private int userId;
private String username;
private List<String> privileges;
// Accessors omitted
}
Run Code Online (Sandbox Code Playgroud)
另一个用于管理登录的 bean:
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
对于托管 Bean,这将检索一个新的 SessionBean,但是对于 CDI,上面的代码只会返回相同的 SessionBean。有什么建议或聪明的想法吗?
困难在于,通过使当前的 HTTP 会话无效,您将在下一个请求中获得一个不同的会话范围的 bean,但直到下一个请求才会如此。
然后不要使会话无效,而是更改会话 ID。换句话说,不要使用HttpSession#invalidate(),而是使用HttpServletRequest#changeSessionId()(自 Servlet 3.1 以来的新功能,鉴于您使用的是 JSF 2.3,您无疑应该已经在使用它)。
在代码中,替换
// force renewal of HTTP session object
context.getExternalContext().invalidateSession();
Run Code Online (Sandbox Code Playgroud)
经过
// force renewal of HTTP session ID
((HttpServletRequest) context.getExternalContext().getRequest()).changeSessionId();
Run Code Online (Sandbox Code Playgroud)
这基本上会更改JSESSIONIDcookie 而不更改HttpSession. 它非常适合防止会话固定。
显式地使会话无效通常仅在注销期间有用。