我遇到了Shiro原生会话管理和JSF CDI SessionScoped bean的问题。我使用的是Shiro 1.4.0和Payara 4.1.1.171(build 137)。这是一种复杂的交互,所以我创建了一个非常简单的场景来演示这个问题(参见下面的代码)。以下是发生的事情:
当我使用Shiro的默认(非本地)会话管理时,我可以登录测试应用程序并按“Say Something New”按钮(使用AJAX),我的屏幕将使用新消息正确更新。我可以根据需要多次重复按“Say Something New”按钮,屏幕将使用新消息正确更新。如果我然后单击“Go Away”按钮,我退出会话,我可以看到我的SessionScoped bean PreDestroy方法被调用,一切都很好。然后我可以再次登录并重复测试,没有任何问题,每次登录时,我都会看到我的SessionScoped bean的PostConstruct方法被正确调用。
但是,当我更改shiro.ini文件以使用本机会话管理时,测试不再有效。相反,这就是发生的事情:我登录到应用程序并看到Hello屏幕。然后我点击“Say Something New”。我立即被重定向回登录屏幕。如果我再次登录,当我点击“Say Something New”按钮时,整个过程会重复。登录似乎工作正常,但似乎使用本机会话管理,Shiro不再跟踪会话?例如,当使用F12开发者工具时,我可以看到JSESSIONID cookie值不断变化,它不应该。 (它没有随非本地会话管理而改变。)
我无论如何都不是四郎的专家,但我不知道我做错了什么?我的shiro.ini文件看起来像Shiro项目页面和Web上显示的许多示例。
我需要使用Shiro的本机会话管理的原因是我想为单点登录实现EhCache SessionDAO。否则,我只会继续使用默认(非本机)会话管理。但是,正如你从我的测试中看到的那样,我还没有实现任何特殊的缓存 - 这只是一个简单的应用程序,出于某种原因表现得很奇怪? (无论如何,对我来说。)我不明白为什么Shiro没有维持会议。
如果有人是Shiro + JSF集成的专家,我会非常感谢一些指针!谢谢!
hello.xhtml:
<!DOCTYPE html>
<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<h:head>
<title>Session Test</title>
<f:facet name="first">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
</f:facet>
</h:head>
<h:body>
<h:form>
<p><h:outputText value="Hi. Session created at: #{testBean.sessionTime}"/></p>
<p><h:outputText value="Latest message: #{testBean.message}"/></p>
<p><h:commandButton ajax="true" value="Say Something New" action="#{testBean.saySomethingNew}"/></p>
<p><h:commandButton value="Go Away" action="#{testBean.sayGoodbye()}"/></p>
</h:form>
</h:body>
</html>
/*
* Test Backing Bean
*/
package com.testco;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
/**
* Session test bean
*/
@Named
@SessionScoped
public class TestBean implements java.io.Serializable {
private static final Logger LOGGER = Logger.getLogger("com.testco");
private Date sessionTime;
private String message;
@PostConstruct
private void initialize() {
LOGGER.log(Level.INFO, "PostConstruct/initialize method called.");
sessionTime = new Date();
}
public String sayGoodbye() {
return "logout.xhtml?faces-redirect=true";
}
public void saySomethingNew() {
setMessage("Something new at: " + new Date());
}
@PreDestroy
private void shutdown() {
LOGGER.log(Level.INFO, "PreDestroy/shutdown method called.");
}
public Date getSessionTime() {
return sessionTime;
}
public void setSessionTime(Date sessionTime) {
this.sessionTime = sessionTime;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
shiro.ini:
[main]
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
securityManager.sessionManager = $sessionManager
# Authentication
# Some custom objects here but this all seems to work fine with non-native session management
authc = com.qed.aes.system.security.VerboseFormAuthenticationFilter
authc.loginUrl = /faces/login.xhtml
aesrealm = com.qed.aes.system.security.AESRealm
securityManager.realms = $aesrealm
# Set up logout behavior
logout.redirectUrl = /faces/hello.xhtml
[urls]
/faces/login.xhtml = authc
/faces/javax.faces.resource/** = anon
/faces/logout.xhtml = logout
/** = authc