Java 如何解决ApacheShiro中注销方法抛出的UnknownSessionException?

Java 如何解决ApacheShiro中注销方法抛出的UnknownSessionException?,java,apache,maven,logout,shiro,Java,Apache,Maven,Logout,Shiro,大家下午好!我在JSF中有一个使用ApacheShiro身份验证的项目。login方法工作正常,但是logout方法抛出UnknownSessionException 以下是我对pom.xml(Maven)的依赖性: Shiro.ini: # ======================= # Shiro INI configuration # ======================= [main] # =============================== # ======

大家下午好!我在JSF中有一个使用ApacheShiro身份验证的项目。login方法工作正常,但是logout方法抛出UnknownSessionException

以下是我对pom.xml(Maven)的依赖性:

Shiro.ini:

# =======================
# Shiro INI configuration
# =======================

[main]

# =============================== 
# =============================== 
# Session Manager SHIRO NATIVE (WEB) 
# =============================== 
# =============================== 

sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager 
securityManager.sessionManager = $sessionManager 
securityManager.sessionManager.globalSessionTimeout = 3600000

shiro.loginUrl = /faces/paginalogin.xhtml
sha256Matcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher

# ===============================
# ===============================
# DATABASE SQL
# ===============================
# ===============================
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.permissionsLookupEnabled = false
jdbcRealm.authenticationCachingEnabled = false
jdbcRealm.authenticationQuery = SELECT senha FROM usuario WHERE email = ?
jdbcRealm.userRolesQuery = SELECT if(nivel='A','admin','normal') FROM usuario WHERE email = ?


# ===============================
# MySQL
# ===============================
dbs=com.mysql.jdbc.jdbc2.optional.MysqlDataSource
#dbs.driverClass = com.mysql.jdbc.Driver
dbs.user=root
dbs.databaseName=shiroexemplo
dbs.serverName=localhost
dbs.portNumber=3306


# ===============================
# ===============================
# DATABASE INSTANCE
# ===============================
# ===============================
jdbcRealm.dataSource=$dbs

[users]
# The 'users' section is for simple deployments
# when you only need a small number of statically-defined
# set of User accounts.

[roles]
admin=*
normal=*

[urls]
/faces/admin/*= authc, roles[admin]
/faces/normal/*=authc, roles[normal]
/faces/paginalogin.xhtml = anon
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager 
securityManager.sessionManager = $sessionManager 
securityManager.sessionManager.globalSessionTimeout = 3600000
Java类:

package com.mycompany.shiroexemplo.bean;

import java.io.Serializable;

import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.servlet.http.HttpSession;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.mycompany.shiroexemplo.dao.UsuarioDAO;
import com.mycompany.shiroexemplo.model.Usuario;

@ManagedBean
@SessionScoped
public class LoginController implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private String username;
    private String senha;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getSenha() {
        return senha;
    }

    public void setSenha(String senha) {
        this.senha = senha;
    }

    public Usuario getUsuario() {
        return usuario;
    }

    public void setUsuario(Usuario usuario) {
        this.usuario = usuario;
    }

    public Usuario usuario;
    private static final Logger log = LoggerFactory.getLogger(LoginController.class);

    public String autenticate() {

        SimpleHash hash = new SimpleHash("md5", senha);
        UsernamePasswordToken token = new UsernamePasswordToken(username, hash.toHex());

        token.setRememberMe(true);
        Subject currentUser = SecurityUtils.getSubject();
        log.info("logando usando o email [" + username + "] e senha [" + hash.toHex() + "]");

        try {
            if (!currentUser.isAuthenticated()) {
                currentUser.login(token);

                UsuarioDAO ud = new UsuarioDAO();
                usuario = ud.getUsuario(username);
            }

            if (currentUser.hasRole("admin")) {
                return "Admin";
            } else {
                return "Normal";
            }
        } catch (AuthenticationException e) {
            e.printStackTrace();
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erro: ", "Usuário ou senha incorretos"));
            return "paginalogin";
        }

    }

    public String logout(ActionEvent ev) {
        Subject currentUser = SecurityUtils.getSubject();
        try {
            if(currentUser.isAuthenticated()){
                currentUser.logout();
            }
        } catch (Exception e) {
            e.printStackTrace();
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erro: ", e.getMessage()));
            return null;
        }
        return "paginalogin";

    }

}

您可以在注销后发出重定向吗?我已经有一段时间没有对Faces做任何事情了,所以我不确定您看到的请求流。基本上,您希望注销请求是重定向之前发生的最后一件事。

谢谢您的回答。做一些研究,我可以解决这个问题。首先,我在我的Shiro.ini中评论了以下几行:

# =======================
# Shiro INI configuration
# =======================

[main]

# =============================== 
# =============================== 
# Session Manager SHIRO NATIVE (WEB) 
# =============================== 
# =============================== 

sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager 
securityManager.sessionManager = $sessionManager 
securityManager.sessionManager.globalSessionTimeout = 3600000

shiro.loginUrl = /faces/paginalogin.xhtml
sha256Matcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher

# ===============================
# ===============================
# DATABASE SQL
# ===============================
# ===============================
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.permissionsLookupEnabled = false
jdbcRealm.authenticationCachingEnabled = false
jdbcRealm.authenticationQuery = SELECT senha FROM usuario WHERE email = ?
jdbcRealm.userRolesQuery = SELECT if(nivel='A','admin','normal') FROM usuario WHERE email = ?


# ===============================
# MySQL
# ===============================
dbs=com.mysql.jdbc.jdbc2.optional.MysqlDataSource
#dbs.driverClass = com.mysql.jdbc.Driver
dbs.user=root
dbs.databaseName=shiroexemplo
dbs.serverName=localhost
dbs.portNumber=3306


# ===============================
# ===============================
# DATABASE INSTANCE
# ===============================
# ===============================
jdbcRealm.dataSource=$dbs

[users]
# The 'users' section is for simple deployments
# when you only need a small number of statically-defined
# set of User accounts.

[roles]
admin=*
normal=*

[urls]
/faces/admin/*= authc, roles[admin]
/faces/normal/*=authc, roles[normal]
/faces/paginalogin.xhtml = anon
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager 
securityManager.sessionManager = $sessionManager 
securityManager.sessionManager.globalSessionTimeout = 3600000
之后,我实现了javax.servlet.http.HttpSession以获取当前会话,如下所示:

HttpSession session = (HttpSession)FacesContext.getCurrentInstance().getExternalContext().getSession(false);
session.invalidate();
FacesContext.getCurrentInstance().getExternalContext.redirect("faces/paginaLogin.xhtml");
最后,我在页面中执行了session.invalidate()和重定向,如下所示:

HttpSession session = (HttpSession)FacesContext.getCurrentInstance().getExternalContext().getSession(false);
session.invalidate();
FacesContext.getCurrentInstance().getExternalContext.redirect("faces/paginaLogin.xhtml");
注销方法的最终版本:

  public void logout(){
        try{
          Subject currentUser = SecurityUtils.getSubject();
          HttpSession session=(HttpSession)FacesContext.getCurrentInstance().getExternalContext().getSession(false);
          if(currentUser.isAuthenticated()){
              session.invalidate();
 FacesContext.getCurrentInstance().getExternalContext().redirect("faces/paginalogin.xhtml"); 

        }
    }catch(Exception e){
            e.printStackTrace();
                    FacesContext.getCurrentInstance().addMessage(null,
                            new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erro: ", e.getMessage()));
        }
    }