Session 如何设计一个无会话的JSF2.0Web应用程序?
我正在一个JSF2.0网站上工作。该网站有两种用户类型:注册用户和注册用户。现在我想知道如何为这两种用户创建会话?对于注册用户,当我的用户登录时,应该有会话,当会话过期时,我将其重定向到您的会话已过期的页面。对于公共用户,根本不应该有会话。表示my public用户没有会话超时,并且他们从未收到您的会话已过期的消息。如何在JSF2.0中实现这种行为 我可以使用过滤器,还是有更好的方法?我还了解到JSF使用托管bean自动创建会话。我可以将这些会话用于我的任务吗 编辑: 我告诉你们我做了什么所以你们最好在这个场景中引导我 我所做的是在我的web应用程序中添加了一个过滤器,如下所示Session 如何设计一个无会话的JSF2.0Web应用程序?,session,jsf-2,Session,Jsf 2,我正在一个JSF2.0网站上工作。该网站有两种用户类型:注册用户和注册用户。现在我想知道如何为这两种用户创建会话?对于注册用户,当我的用户登录时,应该有会话,当会话过期时,我将其重定向到您的会话已过期的页面。对于公共用户,根本不应该有会话。表示my public用户没有会话超时,并且他们从未收到您的会话已过期的消息。如何在JSF2.0中实现这种行为 我可以使用过滤器,还是有更好的方法?我还了解到JSF使用托管bean自动创建会话。我可以将这些会话用于我的任务吗 编辑: 我告诉你们我做了什么所以你
<filter>
<filter-name>SessionTimeoutFilter</filter-name>
<filter-class>util.SessionTimeoutFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SessionTimeoutFilter</filter-name>
<url-pattern>*.xhtml</url-pattern>
</filter-mapping>
String isRegisteredUser = session.getAttribute("logedin").toString();
if (isRegisteredUser.equalsIgnoreCase(("1"))) {
Login login = (Login)session.getAttribute("login");
Enumeration e = session.getAttributeNames();
while (e.hasMoreElements()) {
String attr = (String)e.nextElement();
System.err.println("attr = "+ attr);
Object value = session.getAttribute(attr);
System.err.println("value = "+ value);
} //end of while
long sessionCreationTime = session.getCreationTime();
int sessionCreationTimeInSec = (int)(sessionCreationTime / 1000) % 60;
int sessionCreationTimeInMinutes = (int)((sessionCreationTime / (1000*60)) % 60);
long sessionLastAccessTime = session.getLastAccessedTime();
int sessionLastAccessTimeInSec = (int)(sessionLastAccessTime / 1000) % 60 ;
int sessionLastAccessTimeInMinutes = (int)((sessionLastAccessTime / (1000*60)) % 60 );
int sessionMaxTime = session.getMaxInactiveInterval();
int sessionMaxTimeInMinute = sessionMaxTime / 60 ;
if ((sessionCreationTimeInMinutes - sessionLastAccessTimeInMinutes) - 1 > sessionMaxTimeInMinute) {
System.out.println("Session is expiring in one minute");
}
System.out.println("");
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
现在,若你们第一次输入我的网站的url,那个么这个过滤器就会调用。它变得
Login login = (Login)session.getAttribute("login");
空。因此,它只需移动到我的index.xhtml页面。现在我的index.html页面构造函数调用。这是我的密码
@ManagedBean
//////@RequestScoped
@SessionScoped
public class Login implements Serializable {
//Constructor
public Login() {
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
//getSession(false), which returns null if no session already exists for the current client.
HttpSession session =(HttpSession)externalContext.getSession(false);
if (session == null) {
System.out.println();
} else {
session.setAttribute("logedin", 0); //public user
session.setMaxInactiveInterval(-1); // no session time out
Enumeration e = session.getAttributeNames();
while (e.hasMoreElements()) {
/**
* Here you also get "login" attr. Because when managed bean create the
* session, it sets you managedBean name in the session attribute.
*/
String attr = (String)e.nextElement();
System.err.println("attr = "+ attr);
Object value = session.getAttribute(attr);
System.err.println("value = "+ value);
} //end of while
}
}//end of constructor
} //end of class Login
public String validUser() throws Exception {
ArrayList2d<Object> mainarray = new ArrayList2d<Object>();
mainarray.addRow();
mainarray.add(userName);
mainarray.add(password);
busBeans.usermanagement.users um = new busBeans.usermanagement.users();
ArrayList retrieveList = um.getValidUser(mainarray); //database check of user existence
if (Integer.parseInt(retrieveList.get(0).toString()) == 0) {
ArrayList str = (ArrayList) retrieveList.get(1);
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
//getSession(false), which returns null if no session already exists for the current client.
HttpSession session =(HttpSession)externalContext.getSession(false);
if (session == null) {
System.out.println();
} else {
Enumeration e = session.getAttributeNames();
while (e.hasMoreElements()) {
String attr = (String)e.nextElement();
System.err.println("attr = "+ attr);
Object value = session.getAttribute(attr);
System.err.println("value = "+ value);
} //end of while
}
logedin=true;
session.setAttribute("logedin", 1);
session.setAttribute("firstLastName", str.get(7).toString());
session.setAttribute("getusercredentials", str);
session.setAttribute("sessionUserId", str.get(0).toString());
session.setAttribute("sessionRoleId",str.get(1).toString());
firstLastName = session.getAttribute("firstLastName").toString();
session.setMaxInactiveInterval(60); //1 min
ConnectionUtil.setRgihts(Integer.parseInt(str.get(0).toString()) , Integer.parseInt(str.get(1).toString()) ,Integer.parseInt(str.get(5).toString()));
checkRgihts();
}
} //end of validUser()
当用户第一次访问我的站点时,它并没有登录,所以我将LogeIn会话属性设置为0。现在假设用户输入凭证并按下登录按钮。首先,我的过滤器是invoke,但这次它将获得login属性,并进入我的doFilter else检查,然后进入我的validUser方法。这是我的密码
@ManagedBean
//////@RequestScoped
@SessionScoped
public class Login implements Serializable {
//Constructor
public Login() {
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
//getSession(false), which returns null if no session already exists for the current client.
HttpSession session =(HttpSession)externalContext.getSession(false);
if (session == null) {
System.out.println();
} else {
session.setAttribute("logedin", 0); //public user
session.setMaxInactiveInterval(-1); // no session time out
Enumeration e = session.getAttributeNames();
while (e.hasMoreElements()) {
/**
* Here you also get "login" attr. Because when managed bean create the
* session, it sets you managedBean name in the session attribute.
*/
String attr = (String)e.nextElement();
System.err.println("attr = "+ attr);
Object value = session.getAttribute(attr);
System.err.println("value = "+ value);
} //end of while
}
}//end of constructor
} //end of class Login
public String validUser() throws Exception {
ArrayList2d<Object> mainarray = new ArrayList2d<Object>();
mainarray.addRow();
mainarray.add(userName);
mainarray.add(password);
busBeans.usermanagement.users um = new busBeans.usermanagement.users();
ArrayList retrieveList = um.getValidUser(mainarray); //database check of user existence
if (Integer.parseInt(retrieveList.get(0).toString()) == 0) {
ArrayList str = (ArrayList) retrieveList.get(1);
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
//getSession(false), which returns null if no session already exists for the current client.
HttpSession session =(HttpSession)externalContext.getSession(false);
if (session == null) {
System.out.println();
} else {
Enumeration e = session.getAttributeNames();
while (e.hasMoreElements()) {
String attr = (String)e.nextElement();
System.err.println("attr = "+ attr);
Object value = session.getAttribute(attr);
System.err.println("value = "+ value);
} //end of while
}
logedin=true;
session.setAttribute("logedin", 1);
session.setAttribute("firstLastName", str.get(7).toString());
session.setAttribute("getusercredentials", str);
session.setAttribute("sessionUserId", str.get(0).toString());
session.setAttribute("sessionRoleId",str.get(1).toString());
firstLastName = session.getAttribute("firstLastName").toString();
session.setMaxInactiveInterval(60); //1 min
ConnectionUtil.setRgihts(Integer.parseInt(str.get(0).toString()) , Integer.parseInt(str.get(1).toString()) ,Integer.parseInt(str.get(5).toString()));
checkRgihts();
}
} //end of validUser()
但在会话到期时,如果这是一个注册用户,我还想将用户重定向到Redirer页面。如果这是一个公共用户,我不想重定向它,尽管会话已过期。我可以通过获取属性logedin来检查destroy方法,它是公共用户还是注册用户。但那个么,我怎样才能为注册用户重定向,或者不为公共用户做任何事情呢
如果我的筛选器在会话超时时以某种方式调用,并且我如何通过获取logedin属性1检查这是否是注册用户,并且会话超时已过期,因为对于公共用户,我设置了timeout-1,然后使用RequestDispatcher otherwoise do filterChain.doFilterrequest,response;重定向用户
这就是我实现的场景。我不知道我的方法是否正确?我不知道通过这种方法我将面临什么安全问题。就这样。。现在你们这些人指导我该怎么做
谢谢我知道你的目标是什么,但我不认为不为未经身份验证的用户提供会话是最好的方法 假设一个未经身份验证的用户在Primefaces向导中导航,提供注册帐户的信息,例如选择用户名、提供密码、选择安全问题等 在收集和验证所有信息之前,您不会希望保留这些用户信息,因为用户可能改变了主意,决定不注册?现在,数据库中有一个不完整的用户记录需要清理 答案是,您需要将此信息存储在ViewScoped bean或会话中,直到未经身份验证的用户确认帐户创建,并最终将其持久化 我认为最好的方法是为用户提供一个独特的角色,其中一个角色未经身份验证。使用SpringSecurity3甚至Seam等组件,您应该能够通过会话中用户的角色来控制页面授权
例如,您可以阻止未经身份验证的用户在../app/*中输入页面,或阻止普通用户访问../admin/*中的页面。我使用了类似的方法。首先是一个过滤器。这是我的过滤器
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
//Send request to server after each 1min
// httpServletResponse.setIntHeader("Refresh", 60);
//getSession(false), which returns null if no session already exists for the current client
HttpSession session = httpServletRequest.getSession(false);
if (session == null) {
//session timeout check.
if (httpServletRequest.getRequestedSessionId() != null && !httpServletRequest.isRequestedSessionIdValid()) {
System.out.println("Session has expired");
/**
* getSession() (or, equivalently, getSession(true)) creates a new session if no
* session already exists.
*/
session = httpServletRequest.getSession(true);
session.setAttribute("logedin", "0"); // public user
//httpServletResponse.sendRedirect("http://www.google.com");
httpServletResponse.sendRedirect(timeoutPage);
} else {
session = httpServletRequest.getSession(true);
session.setAttribute("logedin", "0");
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
} else {
String isRegisteredUser = session.getAttribute("logedin").toString();
if (isRegisteredUser.equalsIgnoreCase(("1"))) {
Login login = (Login)session.getAttribute("login");
Enumeration e = session.getAttributeNames();
System.out.println("");
filterChain.doFilter(httpServletRequest, httpServletResponse);
} else if (isRegisteredUser.equalsIgnoreCase(("0"))) {
Enumeration e = session.getAttributeNames();
filterChain.doFilter(httpServletRequest, httpServletResponse);
} //end of else if (isRegisteredUser.equalsIgnoreCase(("0")))
}
} //end of doFilter()
现在,当用户输入我的站点的url时,这个过滤器就会调用。第一次它得到会话null,然后检查会话超时。没有会话超时,因此它会创建会话。将logedin属性设置为零,表示这是公共用户并传递请求。这是我的方法
//constructor
public Login() {
try {
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
HttpServletRequest httpServletRequest = (HttpServletRequest)externalContext.getRequest();
//getSession(false), which returns null if no session already exists for the current client.
HttpSession session =(HttpSession)externalContext.getSession(false);
if (session == null) {
session = httpServletRequest.getSession(true);
session.setAttribute("logedin", "0");
session.setMaxInactiveInterval(-1);
System.out.println();
} else {
session.setAttribute("logedin", "0");
//No session timeout for public users
session.setMaxInactiveInterval(-1);
Enumeration e = session.getAttributeNames();
}
} catch (Exception e) {
System.out.println("Exception in session " + e.getMessage());
}
} //end of constructor
第一次获取会话时,只需覆盖这些值,这样设置相同的属性就不会有任何危害。但在这里我只想问一件事,为公共用户设置没有会话超时可以吗?它会在某个时候损坏我的应用程序吗,比如我的服务器内存不足等等?如果是,那么我如何克服这一问题
现在假设我的用户正在登录。然后我的过滤器调用,这一次它将获得一个会话,因此它将进入我的isRegisterdUser检查并检查值。他得到0,只需传递请求,然后是我的有效用户方法调用
public String validUser() throws Exception {
String returnString = null;
ArrayList2d<Object> mainarray = new ArrayList2d<Object>();
mainarray.addRow();
mainarray.add(userName);
mainarray.add(password);
busBeans.usermanagement.users um = new busBeans.usermanagement.users();
ArrayList retrieveList = um.getValidUser(mainarray);
if (Integer.parseInt(retrieveList.get(0).toString()) == 0) {
ArrayList str = (ArrayList) retrieveList.get(1);
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
//getSession(false), which returns null if no session already exists for the current client.
HttpSession session =(HttpSession)externalContext.getSession(false);
if (session == null) {
System.out.println();
} else {
Enumeration e = session.getAttributeNames();
}
System.out.println();
logedin=true;
//Set session attributes for login users
session.setAttribute("logedin", 1);
session.setAttribute("firstLastName", str.get(7).toString());
session.setAttribute("getusercredentials", str);
session.setAttribute("sessionUserId", str.get(0).toString());
session.setAttribute("sessionRoleId",str.get(1).toString());
session.setAttribute("registeredUser", "true");
/**
* set session timeout for login user
* 1 min = 60 sec
* 5 min = 60 * 5 sec = 300 sec
*/
session.setMaxInactiveInterval(300); //5min
firstLastName = session.getAttribute("firstLastName").toString();
}
return returnString=null;
} //end of validUser()
并通过公开来重定向用户。这就是我如何做到的。我也有一个想法,我在一段时间后刷新页面,我有sessionCreationTime、SessionAsAccessTime和sessionMaxTime。所以我可以做这样的工作
<filter>
<filter-name>SessionTimeoutFilter</filter-name>
<filter-class>util.SessionTimeoutFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SessionTimeoutFilter</filter-name>
<url-pattern>*.xhtml</url-pattern>
</filter-mapping>
String isRegisteredUser = session.getAttribute("logedin").toString();
if (isRegisteredUser.equalsIgnoreCase(("1"))) {
Login login = (Login)session.getAttribute("login");
Enumeration e = session.getAttributeNames();
while (e.hasMoreElements()) {
String attr = (String)e.nextElement();
System.err.println("attr = "+ attr);
Object value = session.getAttribute(attr);
System.err.println("value = "+ value);
} //end of while
long sessionCreationTime = session.getCreationTime();
int sessionCreationTimeInSec = (int)(sessionCreationTime / 1000) % 60;
int sessionCreationTimeInMinutes = (int)((sessionCreationTime / (1000*60)) % 60);
long sessionLastAccessTime = session.getLastAccessedTime();
int sessionLastAccessTimeInSec = (int)(sessionLastAccessTime / 1000) % 60 ;
int sessionLastAccessTimeInMinutes = (int)((sessionLastAccessTime / (1000*60)) % 60 );
int sessionMaxTime = session.getMaxInactiveInterval();
int sessionMaxTimeInMinute = sessionMaxTime / 60 ;
if ((sessionCreationTimeInMinutes - sessionLastAccessTimeInMinutes) - 1 > sessionMaxTimeInMinute) {
System.out.println("Session is expiring in one minute");
}
System.out.println("");
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
这里的想法是,如果您检查了会话超时的剩余时间,那么您可以在会话超时之前使会话无效。因为一旦你的会话过期,你会得到一个空的会话,然后你会
没有要检查的属性。但在一分钟之前,您就拥有了会话和所有会话属性,因此您可以做任何您想做的事情。我不知道这个想法有多可靠,它只是我脑海中浮现的一种方法
还假设用户正在登录,然后突然关闭浏览器。关闭浏览器关闭会话。现在,当您打开浏览器时,会收到一条消息,说明您的会话已过期。我想问你什么时候打开浏览器我能用这张支票吗
if (httpServletRequest.getRequestedSessionId() != null && !httpServletRequest.isRequestedSessionIdValid()) {
System.out.println("Session has expired");
if (session.isNew()) {
/**
* getSession() (or, equivalently, getSession(true)) creates a new session if no
* session already exists.
*/
session = httpServletRequest.getSession(true);
session.setAttribute("logedin", "0"); // public user
filterChain.doFilter(httpServletRequest, httpServletResponse);
} else {
httpServletResponse.sendRedirect("http://www.google.com");
}
}
我使用isNew check是因为我想这样做,如果用户第一次进入您的站点,比如打开他的浏览器,那么他没有看到重定向消息,尽管他的会话由于关闭浏览器而过期
谢谢HHmm实际上我的网站场景是,我为所有用户提供了相同的页面,但是当您为登录用户登录时,页面上会显示一些选项。文件夹中没有页面。与注册用户一样,我的页面位于registeredUsers文件夹中,而对于未注册用户,我的页面位于unRegisteredUsers文件夹中。事实上,坦率地说,这是我第一次研究JavaEE和JSF2.0:。这就是为什么我也不知道JavaEE的良好实践:这仍然可以工作,您可以在托管bean中使用代码来隐藏或显示某些元素,具体取决于会话中用户对象的角色。我认为您的困惑在于您假定会话与经过身份验证的会话相同。不一定:我没有理解你…我假设会话与经过身份验证的会话相同是什么意思。现在我的问题是,如何在会话超时时将注册用户重定向到重定向页面,而不对公共用户执行任何操作。我也编辑了我的帖子。您可以看到我是如何完成会话的。@BalusC Hi抱歉,您是对的,我正在使用Majorra 2.0.2。当我的GlassFish容器运行时,它将初始化Majorra 2.0.2。无论如何,再次抱歉,那一次我不知道,并对你说我没有使用Majorra。