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

Posted

技术标签:

【中文标题】会话固定 - 登录后删除会话并创建新会话 - 但用户不再登录【英文标题】:session fixation - delete session after login and make a new session - but user is then not logged in anymore 【发布时间】:2012-04-07 11:20:58 【问题描述】:

我在 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 */


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);

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

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

有什么方法可以在创建后将新的 LoginController 添加到新会话中?

或者常用的方法是什么?

【问题讨论】:

【参考方案1】:

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

您基本上需要手动重新创建会话范围 bean 并将其放入新会话中 失效。

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

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

顺便说一句,当你走这条路时,你也可以让你的LoginController成为一个视图范围的bean,只在会话中处理User

ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
externalContext.invalidateSession();
externalContext.getSessionMap().put("user", user);

#user 可以在整个 EL 上下文中使用它,也可以在托管属性中使用它;它不一定是 JSF 托管 bean)

【讨论】:

再一次...谢谢你!这很完美....如果我需要 userProvider 再次注销...但是如果我尝试注销,我会做类似:loggedIn = false; user.setLoggedIn(false);userProvider.saveChangedUser(user); ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext(); externalContext.invalidateSession(); 但随后 userprovider 是空的。我也尝试将 userProvider 也放入会话,但无法正常工作 - 出现该错误后,我无法再次登录 - 因为 userProvider 为空...... @Inject 属于 CDI,在 JSF @ManagedBean 中不起作用,仅在 CDI @Named 中起作用。将UserProvider 设为@Stateless 并通过@EJB 注入。 为什么他的 LoginController 必须是 viewscoped? Requestscoped 也很好,不是吗?只是要清楚 @Ced:视情况而定。当@RequestScoped 似乎没有成功时,初学者经常抓住@SessionScoped。但是,如果 @RequestScoped 也可以正常工作,请务必使用它。

以上是关于会话固定 - 登录后删除会话并创建新会话 - 但用户不再登录的主要内容,如果未能解决你的问题,请参考以下文章

新会话的Spring安全创建

如何监控正在运行的屏幕会话并在最后一个会话结束后开始新会话?

使用_IECreate()创建新会话

访问登录页面时创建的会话过多?

Appium 错误:无法创建新会话。 (原始错误:没有从 Chromedriver 获得会话重定向)

Laravel 为每个请求创建一个新会话