我有一个班级:
@SessionScoped
public class LoggedUser {
private User user;
...
}
我用来跟踪用户是否已登录我的应用程序。
在我的Struts2应用程序中,我有一个Interceptor来检查用户是否已被登录,如果没有,他会被转发到登录页面。
public class LoggedUserInterceptor extends AbstractInterceptor {
private static final long serialVersionUID = 2822434409188961460L;
@Inject
private LoggedUser loggedUser;
@Override
public String intercept(ActionInvocation invocation) throws Exception {
if(loggedUser==null || !loggedUser.isLogged()){
return "login";
}
return invocation.invoke();
}
}
会话超时时出现问题。 LoggdeUser对象永远不会为null或已删除。我总是最后一次。
我添加了一个会话监听器。
public class SessionListener implements HttpSessionListener {
private static Logger logger = Logger.getLogger(SessionListener.class.getName());
@Override
public void sessionCreated(HttpSessionEvent event) {
logger.info("sessionCreated = " + event.getSession().getId());
}
@Override
public void sessionDestroyed(HttpSessionEvent event) {
logger.info("sessionDestroyed = " + event.getSession().getId());
}
}
我看到sessionDestroyed被调用了,但是当我再次进入我的Interceptor时...... LoggedUser永远不会为新会话重新创建。
为什么?
我的Struts2登录操作是
public class LoginUserAction extends ActionSupport implements ModelDriven<LoggedUser>, ServletRequestAware {
...
@Inject
private LoggedUser loggedUser;
public String execute() throws Exception {
...
loggerUser.setLoggedTime(now);
...
return SUCCESS;
}
我在web.xml中也添加了
session-config session-timeout 2 /session-timeout /session-config
答案 0 :(得分:1)
我对Struts2一无所知,但我的猜测是拦截器的范围比会话范围更广。换句话说,拦截器实例的保持时间比会话长。当会话结束时,Guice不能也不会将注入的字段设置为null
,也不会自动重新注入对象。
如果在生命周期较长的对象中使用生命周期较短的对象(例如RequestScoped
对象内的SessionScoped
对象或SessionScoped
对象,则需要执行的操作在单身内部)为较短生命的物体注入Provider
。
在您的情况下,我认为这可能是您所需要的:
public class LoggedUserInterceptor extends AbstractInterceptor {
private static final long serialVersionUID = 2822434409188961460L;
@Inject
private Provider<LoggedUser> loggedUserProvider;
@Override
public String intercept(ActionInvocation invocation) throws Exception {
LoggedUser loggedUser = loggedUserProvider.get();
if(loggedUser==null || !loggedUser.isLogged()){
return "login";
}
return invocation.invoke();
}
}
答案 1 :(得分:0)
我不知道guice但拦截器可以使用会话,并且可以通过SessionAware随时可用于该操作:
ActionInvocation提供对会话的访问。以下是“身份验证”拦截器的一部分。如果没有“User”对象,则返回Action.LOGIN。
public String intercept(ActionInvocation invocation) throws Exception {
Map session = invocation.getInvocationContext().getSession();
appLayer.User user = (appLayer.User) session.get("User");
if (user == null){
return Action.LOGIN;
}
return invocation.invoke();
}
我只在用户登录时将用户对象放在会话上。
在登录操作中,我将用户对象放在会话上:
public class Login extends ActionSupport implements SessionAware {
private Map<String, Object> session;
private String userName;
private String password;
public String execute() {
//use DB authentication once this works
//if ("ken".equalsIgnoreCase(userName) && "ken".equalsIgnoreCase(password)){
try {
User user = new User(userName, password);
session.put("User", user);
return ActionSupport.SUCCESS;
} catch (Exception e) {
System.out.println("There was an exception" + e.getMessage());
return ActionSupport.LOGIN;
}
}
public void validate() {
String user = this.getUserName();
String pass = this.getPassword();
//This block is a bit redundant but I couldn't figure out how
//to get just the hibernate part to report an exception on Username/pass
if (!StringUtils.isBlank(this.getUserName()) && !StringUtils.isBlank(this.getPassword())) {
try {
Class.forName("com.ibm.as400.access.AS400JDBCDriver").newInstance();
String url = "jdbc:as400://192.168.1.14";
DriverManager.getConnection(url, user, pass).close();
} catch (Exception e) {
addFieldError("login.error.authenticate", "Bad Username / Password");
}
}
if (StringUtils.isBlank(getUserName())) {
addFieldError("login.error.name", "Missing User Name");
}
if (StringUtils.isBlank(getPassword())) {
addFieldError("login.error.password", "Missing Password");
}
//else both are blank don't report an error at this time
}
... getters/setters....
}//end class
如果我没记错的话,至少部分来自“Struts2 in Action”。无论如何,我是DI的忠实信徒,但是因为会话很容易从拦截器和我不打扰的行动中获取。
答案 2 :(得分:0)
最简单的方法是最终将令牌放在登录会话中并使用拦截器进行检查
@Override
public String intercept(ActionInvocation invocation) throws Exception {
loggedUser = (LoggedUser) invocation.getInvocationContext().getSession().get(LoggedUser.SESSIONTOKEN);
if(loggedUser==null || !loggedUser.isLogged()){
logger.info("loggedUser not present in session");
return "login";
}
return invocation.invoke();
}
request.getSession().setAttribute(LoggedUser.SESSIONTOKEN, loggedUser);