How to solve UnknownSessionException thrown in logout method in Apache Shiro?

空扰寡人 提交于 2019-12-12 04:08:30

问题


Good afternoon guys! I have a project in JSF that uses Apache Shiro Authentication. The login method works fine, but the logout method throw UnknownSessionException.

Here is my dependencies on pom.xml(Maven):

<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-core -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.3.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-web -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-web</artifactId>
            <version>1.3.2</version>
        </dependency> 

StackTrace:

abr 07, 2017 9:20:26 PM com.sun.faces.context.AjaxExceptionHandlerImpl handlePartialResponseError
GRAVE: java.lang.IllegalStateException: org.apache.shiro.session.UnknownSessionException: There is no session with id [e3b18152-09c3-4644-8815-f3bf7dd77513]
    at org.apache.shiro.web.servlet.ShiroHttpSession.getAttribute(ShiroHttpSession.java:133)
    at com.sun.faces.context.SessionMap.put(SessionMap.java:127)
    at com.sun.faces.context.SessionMap.put(SessionMap.java:61)
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.getResponseEncoding(FaceletViewHandlingStrategy.java:1310)
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.createResponseWriter(FaceletViewHandlingStrategy.java:1198)
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:405)
    at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:134)
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:659)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61)
    at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
    at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
    at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
    at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
    at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
    at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
    at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
    at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
    at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
    at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
    at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383)
    at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
    at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:528)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1100)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:687)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1520)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1476)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source)
Caused by: org.apache.shiro.session.UnknownSessionException: There is no session with id [e3b18152-09c3-4644-8815-f3bf7dd77513]
    at org.apache.shiro.session.mgt.eis.AbstractSessionDAO.readSession(AbstractSessionDAO.java:170)
    at org.apache.shiro.session.mgt.DefaultSessionManager.retrieveSessionFromDataSource(DefaultSessionManager.java:236)
    at org.apache.shiro.session.mgt.DefaultSessionManager.retrieveSession(DefaultSessionManager.java:222)
    at org.apache.shiro.session.mgt.AbstractValidatingSessionManager.doGetSession(AbstractValidatingSessionManager.java:118)
    at org.apache.shiro.session.mgt.AbstractNativeSessionManager.lookupSession(AbstractNativeSessionManager.java:148)
    at org.apache.shiro.session.mgt.AbstractNativeSessionManager.lookupRequiredSession(AbstractNativeSessionManager.java:152)
    at org.apache.shiro.session.mgt.AbstractNativeSessionManager.getAttribute(AbstractNativeSessionManager.java:249)
    at org.apache.shiro.session.mgt.DelegatingSession.getAttribute(DelegatingSession.java:141)
    at org.apache.shiro.session.ProxiedSession.getAttribute(ProxiedSession.java:121)
    at org.apache.shiro.web.servlet.ShiroHttpSession.getAttribute(ShiroHttpSession.java:131)
    ... 49 more

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

Java class:

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

    }

}

回答1:


Can you issue a redirect after logout? It's been a while since I've done anything with Faces, so I'm not sure of the request flow that you are seeing. Basically, you would want the logout request to be the last thing to happen before a redirect.




回答2:


thanks for answer me. Doing some researches, I could solve the problem. First, I commented these lines in my Shiro.ini:

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

After that, I implemented javax.servlet.http.HttpSession to get the current session, like this:

HttpSession session = (HttpSession)FacesContext.getCurrentInstance().getExternalContext().getSession(false);

Finally, I did a session.invalidate() and also a redirect in the page, like this:

session.invalidate();
FacesContext.getCurrentInstance().getExternalContext.redirect("faces/paginaLogin.xhtml");

The final version of logout method :

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


来源:https://stackoverflow.com/questions/43299354/how-to-solve-unknownsessionexception-thrown-in-logout-method-in-apache-shiro

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!