Trace:
Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision Next revision Both sides next revision | ||
jvx:code_snippets [2018/02/06 10:33] admin |
jvx:code_snippets [2019/05/03 09:24] admin [Detect Production mode] |
||
---|---|---|---|
Line 2178: | Line 2178: | ||
ALTER TABLE CONTRACT enable ALL triggers; | ALTER TABLE CONTRACT enable ALL triggers; | ||
ALTER TABLE ACTIVITY enable ALL triggers; | ALTER TABLE ACTIVITY enable ALL triggers; | ||
+ | </file> | ||
+ | |||
+ | ==== Authentication/User logging ==== | ||
+ | |||
+ | Some applications need detailed information about successful or failed user logins. If you have such requirement, you could create a custom security manager to solve the problem. The security manager will be used for user authentication, so it's the right place to start. | ||
+ | |||
+ | We use the database security manager as base class: | ||
+ | |||
+ | <file java LoggingSecurityManager.java> | ||
+ | package com.sibvisions.apps.vaadin.web; | ||
+ | |||
+ | public class LoggingSecurityManager extends DBSecurityManager | ||
+ | { | ||
+ | private PreparedStatement psLockedUsers; | ||
+ | |||
+ | @Override | ||
+ | protected boolean isPasswordValid(ISession pSession, String pPassword) throws Exception | ||
+ | { | ||
+ | // additional check: locked user | ||
+ | |||
+ | ResultSet resultSet = null; | ||
+ | |||
+ | try | ||
+ | { | ||
+ | psLockedUsers.clearParameters(); | ||
+ | psLockedUsers.setString(1, pSession.getUserName()); | ||
+ | psLockedUsers.execute(); | ||
+ | |||
+ | resultSet = psLockedUsers.getResultSet(); | ||
+ | |||
+ | if (resultSet.next()) | ||
+ | { | ||
+ | throw new SilentAbortException(); | ||
+ | } | ||
+ | } | ||
+ | finally | ||
+ | { | ||
+ | CommonUtil.close(resultSet); | ||
+ | } | ||
+ | |||
+ | return super.isPasswordValid(pSession, pPassword); | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | public synchronized void validateAuthentication(ISession pSession) throws Exception | ||
+ | { | ||
+ | String result = null; | ||
+ | |||
+ | Throwable error = null; | ||
+ | |||
+ | try | ||
+ | { | ||
+ | super.validateAuthentication(pSession); | ||
+ | |||
+ | result = Constants.RESULT_OK; | ||
+ | } | ||
+ | catch (SilentAbortException sae) | ||
+ | { | ||
+ | result = Constants.RESULT_IGNORE; | ||
+ | error = sae; | ||
+ | |||
+ | throw sae; | ||
+ | } | ||
+ | catch (SecurityException se) | ||
+ | { | ||
+ | result = Constants.RESULT_DENIED; | ||
+ | error = se; | ||
+ | |||
+ | throw se; | ||
+ | } | ||
+ | catch (Exception ex) | ||
+ | { | ||
+ | result = Constants.RESULT_ERROR; | ||
+ | error = ex; | ||
+ | |||
+ | error(ex); | ||
+ | |||
+ | throw ex; | ||
+ | } | ||
+ | finally | ||
+ | { | ||
+ | try | ||
+ | { | ||
+ | pSession.callAction("dbLog", Constants.TYPE_LOGIN, error, result); | ||
+ | } | ||
+ | catch (Throwable thr) | ||
+ | { | ||
+ | error(thr); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | public synchronized void logout(ISession pSession) | ||
+ | { | ||
+ | String result = null; | ||
+ | Throwable error = null; | ||
+ | |||
+ | try | ||
+ | { | ||
+ | super.logout(pSession); | ||
+ | |||
+ | if (Boolean.parseBoolean((String)pSession.getProperty("userlogout"))) | ||
+ | { | ||
+ | result = Constants.RESULT_OK; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | result = Constants.RESULT_EXPIRED; | ||
+ | } | ||
+ | } | ||
+ | catch (Exception ex) | ||
+ | { | ||
+ | result = Constants.RESULT_ERROR; | ||
+ | error = ex; | ||
+ | |||
+ | error(ex); | ||
+ | } | ||
+ | finally | ||
+ | { | ||
+ | try | ||
+ | { | ||
+ | pSession.callAction("dbLog", Constants.TYPE_LOGOUT, error, result); | ||
+ | } | ||
+ | catch (Throwable eLog) | ||
+ | { | ||
+ | error(eLog); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | protected void initStatements(Connection pConnection) throws Exception | ||
+ | { | ||
+ | super.initStatements(pConnection); | ||
+ | |||
+ | psLockedUsers = prepareStatement(pConnection, "select * from LOCKS where USERNAME = ?"); | ||
+ | } | ||
+ | |||
+ | } // LoggingSecurityManager | ||
+ | </file> | ||
+ | |||
+ | The clue is that the log method **dbLog** was implemented in the session LCO of our application because we re-use the business logic in our security manager. Here's the missing method: | ||
+ | |||
+ | <file java> | ||
+ | public void dbLog(int pAction, Throwable pError, String pStatus) | ||
+ | { | ||
+ | ILogger log = LoggerFactory.getInstance(getClass()); | ||
+ | |||
+ | log.info("Log action ", pAction, pError, pStatus); | ||
+ | | ||
+ | try | ||
+ | { | ||
+ | getDBAccess().executeProcedure("log", | ||
+ | pAction, | ||
+ | SessionContext.getCurrentSession().getUserName(), | ||
+ | new Timestamp(System.currentTimeMillis())); | ||
+ | } | ||
+ | catch (Exception ex) | ||
+ | { | ||
+ | log.error(ex); | ||
+ | } | ||
+ | } | ||
+ | </file> | ||
+ | |||
+ | ==== Detect Production mode ==== | ||
+ | |||
+ | If you use the DBSecurityManager, it's possible to set the environment. The environment is a marker for the database connection, e.g.: | ||
+ | |||
+ | <file xml> | ||
+ | <?xml version="1.0" encoding="UTF-8"?> | ||
+ | |||
+ | <application> | ||
+ | <securitymanager> | ||
+ | <class>com.sibvisions.rad.server.security.DBSecurityManager</class> | ||
+ | <environment>prod</environment> | ||
+ | </securitymanager> | ||
+ | <datasource> | ||
+ | <db name="default"> | ||
+ | <url>jdbc:oracle:thin:@dbserver:1521:XE</url> | ||
+ | <username>test</username> | ||
+ | <username_prod>prod</username_prod> | ||
+ | <password>test</password> | ||
+ | <password_prod>prod</password_prod> | ||
+ | </db> | ||
+ | </datasource> | ||
+ | </application> | ||
+ | </file> | ||
+ | |||
+ | The marker will be used as postfix for the detection of datasource credentials. In the example, the postfix is **prod** and the **username_prod** will be used instead of **username**. If not tag with environment postfix is available, the standard tag will be used. | ||
+ | |||
+ | If you want to use the environment in your source code, simply call: | ||
+ | |||
+ | <file java> | ||
+ | String env = SessionContext.getCurrentSessionConfig().getProperty("/application/securitymanager/environment"); | ||
</file> | </file> |