Detect timeout [message #1071494] |
Sat, 20 July 2013 04:35  |
Eclipse User |
|
|
|
Hi,
At the server side, in tomcat, a time out is set: <session-timeout>30</session-timeout>). When there is no user activity for more then 30 minutes from a swing client and the user restarts his activity, all kinds of processing errors occur because the session is not there anymore.
How can I handle this situation in a way that I give a proper error message so the user knows that he has to log-on again.
Regards Bertin
|
|
|
|
|
|
|
Re: Detect timeout [message #1072916 is a reply to message #1072353] |
Tue, 23 July 2013 15:16   |
Eclipse User |
|
|
|
Hi Andreas,
below the code that thows the exception and the security filter.
The code that throws the exception executes ServerSession.get().getMpxDatabaseNummer(); and/or ServerSession.get().getMpxVestigingNaam(); at least one of these methods must return a valid value, but in the case the time-out is expired, it does not return anything.
Regards Bertin
/**
*
*/
public class MpxSqlServiceProvider {
// db1
private static final String RID_1 = "RID 1";
private static final String RID_2 = "RID 2";
private static final String RID_3 = "RID 3";
// db2
private static final String RID_4 = "RID 4";
private static final String RID_5 = "RID 5";
private static final String RID_6 = "RID 6";
private static final String RID_7 = "RID 7";
// db3
private static final String RID_8 = "RID 8";
private static final String RID_9 = "RID 9";
private static final String RID_10 = "RID 10";
// db4
private static final String RID_11 = "RID 11";
private static final String RID_12 = "RID 12";
private static final String RID_13 = "RID 13";
public static Class<? extends AbstractSqlService> getSqlServiceClass() throws ProcessingException {
int databaseNummer = ServerSession.get().getMpxDatabaseNummer();
//System.out.println("Database nummer = " + databaseNummer);
switch (databaseNummer) {
case 1:
return Mpx1SqlService.class;
case 2:
return Mpx2SqlService.class;
case 3:
return Mpx3SqlService.class;
case 4:
return Mpx4SqlService.class;
default: {
//System.out.println("Database nummer not valid, find by vestigingName");
String vestigingName = ServerSession.get().getMpxVestigingNaam();
if (RID_1.equals(vestigingName) || RID_2.equals(vestigingName) || RID_3.equals(vestigingName)) {
return Mpx1SqlService.class;
}
else if (RID_4.equals(vestigingName) || RID_5.equals(vestigingName) || RID_6.equals(vestigingName) || RID_7.equals(vestigingName)) {
return Mpx2SqlService.class;
}
else if (RID_8.equals(vestigingName) || RID_9.equals(vestigingName) || RID_10.equals(vestigingName)) {
return Mpx3SqlService.class;
}
else if (RID_11.equals(vestigingName) || RID_12.equals(vestigingName) || RID_13.equals(vestigingName)) {
return Mpx4SqlService.class;
}
else {
throw new ProcessingException("No sqlService found for vestiging " + vestigingName); // this is line 72
}
}
}
}
}
and here the security filter we use:
public class SaltedDataSourceSecurityFilter extends AbstractChainableSecurityFilter {
private static final IScoutLogger LOG = ScoutLogManager.getLogger(SaltedDataSourceSecurityFilter.class);
public static final String PROP_BASIC_ATTEMPT = "SaltedDataSourceSecurityFilter.basicAttempt";
private String m_jdbcUserName;
private String m_jdbcPassword;
private String m_jdbcDriverName;
private String m_jdbcMappingName;
private String m_selectStatement;
private String m_selectSaltStatement = "select salt from account where name = ?";
private boolean m_useJndiConnection = false;
private String m_jndiName;
private String m_jndiInitialContextFactory;
private String m_jndiProviderUrl;
private String m_jndiUrlPkgPrefixes;
@Override
public void init(FilterConfig config0) throws ServletException {
super.init(config0);
FilterConfigInjection.FilterConfig config = new FilterConfigInjection(config0, getClass()).getAnyConfig();
String useJndiConnectionString = config.getInitParameter("useJndiConnection");
m_useJndiConnection = Boolean.parseBoolean(useJndiConnectionString);
m_jdbcDriverName = getInitParam(config, "jdbcDriverName");
m_jdbcMappingName = getInitParam(config, "jdbcMappingName");
m_jdbcUserName = getInitParam(config, "jdbcUsername");
m_jdbcPassword = getInitParam(config, "jdbcPassword");
m_selectStatement = getInitParam(config, "selectUserPass");
m_jndiName = getInitParam(config, "jndiName");
m_jndiInitialContextFactory = config.getInitParameter("jndiInitialContextFactory");
m_jndiProviderUrl = config.getInitParameter("jndiProviderUrl");
m_jndiUrlPkgPrefixes = config.getInitParameter("jndiUrlPkgPrefixes");
}
private String getInitParam(FilterConfig filterConfig, String paramName) throws ServletException {
String paramValue = filterConfig.getInitParameter(paramName);
if ((m_useJndiConnection && paramName.indexOf("jndi") != -1 && paramValue == null) || (!m_useJndiConnection && paramName.indexOf("jdbc") != -1 && paramValue == null)) {
throw new ServletException("Missing init-param with name '" + paramName + "'.");
}
return paramValue;
}
protected boolean isValidUser(String username, String password) throws ServletException {
Connection databaseConnection = null;
PreparedStatement stmt = null;
try {
if (m_useJndiConnection) {
databaseConnection = createJndiConnection();
}
else {
databaseConnection = createJdbcDirectConnection();
}
stmt = databaseConnection.prepareStatement(m_selectStatement);
stmt.setString(1, username);
stmt.setString(2, password);
stmt.execute();
ResultSet resultSet = stmt.getResultSet();
return (resultSet.next() && resultSet.getString(1).equals(username));
}
catch (Exception e) {
//LOG.error("Cannot SELECT user/pass.", e);
throw new ServletException(e.getMessage(), e);
}
finally {
try {
if (stmt != null) {
stmt.close();
stmt = null;
}
}
catch (SQLException e) {
//LOG.warn("Exception in close stmt!", e);
}
try {
if (databaseConnection != null) {
databaseConnection.close();
databaseConnection = null;
}
}
catch (SQLException e) {
//LOG.warn("Exception in close connection!", e);
}
}
}
@Override
protected int negotiate(HttpServletRequest req, HttpServletResponse resp, PrincipalHolder holder) throws IOException, ServletException {
String h = req.getHeader("Authorization");
if (h != null && h.matches("Basic .*")) {
String[] a = new String(Base64Utility.decode(h.substring(6)), "ISO-8859-1").split(":", 2);
String user = a[0].toLowerCase();
String pass = a[1];
if (user != null && pass != null) {
String salt = getSalt(user);
String passEncrypted = encryptPass(pass + salt);
if (isValidUser(user, passEncrypted)) {
holder.setPrincipal(new SimplePrincipal(user));
return STATUS_CONTINUE_WITH_PRINCIPAL;
}
}
}
int attempts = getBasicAttempt(req);
if (attempts > 2) {
return STATUS_CONTINUE_CHAIN;
}
else {
setBasicAttept(req, attempts + 1);
resp.setHeader("WWW-Authenticate", "Basic realm=\"" + getRealm() + "\"");
return STATUS_CONTINUE_CHAIN;
}
}
private String getSalt(String username) throws ServletException {
String result = null;
Connection databaseConnection = null;
PreparedStatement stmt = null;
try {
if (m_useJndiConnection) {
databaseConnection = createJndiConnection();
}
else {
databaseConnection = createJdbcDirectConnection();
}
stmt = databaseConnection.prepareStatement(m_selectSaltStatement);
stmt.setString(1, username);
stmt.execute();
ResultSet resultSetSalt = stmt.getResultSet();
while (resultSetSalt.next()) {
result = resultSetSalt.getString("salt");
}
}
catch (Exception e) {
//LOG.error("Cannot SELECT user/pass.", e);
throw new ServletException(e.getMessage(), e);
}
finally {
try {
if (stmt != null) {
stmt.close();
stmt = null;
}
}
catch (SQLException e) {
//LOG.warn("Exception in close stmt!", e);
}
try {
if (databaseConnection != null) {
databaseConnection.close();
databaseConnection = null;
}
}
catch (SQLException e) {
//LOG.warn("Exception in close connection!", e);
}
}
return result;
}
private String encryptPass(String pass) throws ServletException {
String passEncrypted = null;
if (pass != null) {
try {
passEncrypted = Base64Utility.encode(EncryptionUtility.signMD5(pass.getBytes()));
}
catch (NoSuchAlgorithmException e) {
//LOG.error("couldn't create the password", e);
throw new ServletException("couldn't create the password", e);
}
}
return passEncrypted;
}
private int getBasicAttempt(HttpServletRequest req) {
int basicAtttempt = 0;
Object attribute = req.getSession().getAttribute(PROP_BASIC_ATTEMPT);
if (attribute instanceof Integer) {
basicAtttempt = ((Integer) attribute).intValue();
}
return basicAtttempt;
}
private void setBasicAttept(HttpServletRequest req, int attempts) {
req.getSession().setAttribute(PROP_BASIC_ATTEMPT, attempts);
}
protected Connection createJdbcDirectConnection() throws ClassNotFoundException, SQLException {
Class.forName(m_jdbcDriverName);
return DriverManager.getConnection(m_jdbcMappingName, m_jdbcUserName, m_jdbcPassword);
}
protected Connection createJndiConnection() throws NamingException, SQLException {
InitialContext initialContext = null;
String jndiName = m_jndiName;
String jndiInitialContextFactory = m_jndiInitialContextFactory;
String jndiProviderUrl = m_jndiProviderUrl;
String jndiUrlPkgPrefixes = m_jndiUrlPkgPrefixes;
if (LOG.isInfoEnabled()) LOG.info("Opening rmi connection to: " + jndiName + "," + m_jdbcUserName);
if (LOG.isInfoEnabled()) LOG.info(" using initial context factory: " + jndiInitialContextFactory);
if (LOG.isInfoEnabled()) LOG.info(" using provider url: " + jndiProviderUrl);
Hashtable<String, String> ht = new Hashtable<String, String>();
if (jndiInitialContextFactory != null) {
ht.put(Context.INITIAL_CONTEXT_FACTORY, jndiInitialContextFactory);
}
if (jndiProviderUrl != null) {
ht.put(Context.PROVIDER_URL, jndiProviderUrl);
}
if (jndiUrlPkgPrefixes != null) {
ht.put(Context.URL_PKG_PREFIXES, jndiUrlPkgPrefixes);
}
DataSource dataSource = null;
if (ht.size() > 0) {
initialContext = new InitialContext(ht);
}
else {
initialContext = new InitialContext();
}
dataSource = (DataSource) initialContext.lookup(jndiName);
// Grab a connection
Connection conn;
if (m_jdbcUserName != null && m_jdbcPassword != null) {
conn = dataSource.getConnection(m_jdbcUserName, m_jdbcPassword);
}
else {
conn = dataSource.getConnection();
}
conn.setAutoCommit(false);
return conn;
}
}
|
|
|
|
Re: Detect timeout [message #1074191 is a reply to message #1072959] |
Fri, 26 July 2013 04:52  |
Eclipse User |
|
|
|
Hi,
got some logging info:
// After login the ServerSession is created which is expected. I executed some actions so it is visible that the databaseNumber and VestigingNaam are set.
ServerSession now constructed
ServerSession.execLoadSession now called
ServerSession.setMpxDatabaseNummer now called
ServerSession.setMpxVestigingNaam now called
Database nummer in MpxSqlServiceProvider = 1
Database nummer in MpxSqlServiceProvider = 1
Database nummer in MpxSqlServiceProvider = 1
// now I waited until timeout exceeded
ServerSession now constructed
ServerSession.execLoadSession now called
Database nummer in MpxSqlServiceProvider = 0
Database nummer in MpxSqlServiceProvider not valid, find by vestigingName
Database nummer in MpxSqlServiceProvider = 0
Database nummer in MpxSqlServiceProvider not valid, find by vestigingName
After the time-out is exceeded and an actions are executed from the client a new ServerSession is automatically created. I think this is strange.
Regards Bertin
|
|
|
Powered by
FUDForum. Page generated in 0.08712 seconds