会话固定 - 登录后删除会话并创建新会话 - 但用户不再登录

Joe*_*erg 6 security session login java-ee-6 jsf-2

我在JBoss AS 7上使用jsf2.0和java ee6

我有一个看起来像这样的LoginController.java:

@ManagedBean(name = "loginController")
@SessionScoped
public class LoginController implements Serializable{

    private static final long serialVersionUID = 1119172305268193508L;

    @Inject
    private UserProvider userProvider;

    @PostConstruct
    public void initNewUser() {
        user = new User();
    }

    private User user;

    private String accountName;

    private String password;

    public String ownLogin() throws Exception {

        HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance()
                .getExternalContext().getRequest();


        if (accountName != null) {
            try {


                if (exists(accountName)) {

                    user = userProvider.findUserByAccountName(accountName);

                    if (verifyPassword(user, password)) {

                        userProvider.saveChangedUser(user);


                        // OWASP SAYS: after login, destroy the session make a new one 
                        // a so called handover
                        // Destroy the session
                        FacesContext facesContext = FacesContext.getCurrentInstance();

                        HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(false);
                        if(session != null){
                            session.invalidate();
                        }
                        // create new session after logout
                        session = (HttpSession) facesContext.getExternalContext().getSession(true);
                    setLogin(true);
            }                   
    }

/* some getters and setters */

}
Run Code Online (Sandbox Code Playgroud)

OWASP说,出于安全原因,登录后应删除会话(参见:V3.7)

我在我的代码中执行此操作:

FacesContext facesContext = FacesContext.getCurrentInstance();

                            HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(false);
                            if(session != null){
                                session.invalidate();
                            }
                            // create new session after logout
                            session = (HttpSession) facesContext.getExternalContext().getSession(true);
Run Code Online (Sandbox Code Playgroud)

首先,我删除旧会话,然后我创建一个新会话.
在此之后,我将登录设置为true ...

当然,在运行整个代码之后,用户没有登录,因为LoginController是在旧的会话范围内管理的 - 并且在新的会话范围内,在范围内有一个新的LoginController而没有用户...

有没有办法,在创建后将新的LoginController添加到新会话中?

或者通常的方法是什么?

Bal*_*usC 5

当您使会话无效时,其所有属性都将在响应结束时被丢弃。但是,您在仅存在于旧会话中的会话范围 bean 实例上设置登录状态。

您基本上需要手动重新创建会话作用域 bean,并在失效后将其放入新会话中。

ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
externalContext.invalidateSession();
LoginController loginController = new LoginController();
loginController.setUser(user);
externalContext.getSessionMap().put("loginController", loginController);
Run Code Online (Sandbox Code Playgroud)

(看,没有丑陋的javax.servlet进口了!)

顺便说一句,当你这样做时,你也可以只制作LoginController一个视图范围的bean并User只在会话中处理。

ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
externalContext.invalidateSession();
externalContext.getSessionMap().put("user", user);
Run Code Online (Sandbox Code Playgroud)

(它将#{user}在整个 EL 上下文中可用,也在托管属性中可用;它不一定需要是 JSF 托管 bean)

  • `@Inject` 属于 CDI,在 JSF `@ManagedBean` 中不起作用,只能在 CDI `@Named` 中工作。使 `UserProvider` 成为 `@Stateless` 并通过 `@EJB` 注入它。 (2认同)