Last active
December 23, 2015 10:09
-
-
Save adityamukho/6619998 to your computer and use it in GitHub Desktop.
BIRT SSO with Drupal 7
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class AuthFilter implements Filter | |
{ | |
private static final boolean debug = false; | |
// The filter configuration object we are associated with. If | |
// this value is null, this filter instance is not currently | |
// configured. | |
private FilterConfig filterConfig = null; | |
public AuthFilter () | |
{ | |
} | |
private boolean validateSession (HttpServletRequest request, Map<String, String> authorizedSessions) | |
{ | |
Cookie[] cookies = request.getCookies (); | |
if (cookies != null) | |
{ | |
for (int i = 0; i < cookies.length; ++i) | |
{ | |
String remoteSession = cookies[i].getValue (); | |
if (authorizedSessions.containsKey (remoteSession)) | |
{ | |
String localSession = authorizedSessions.get (remoteSession); | |
String jSessionId = request.getSession ().getId (); | |
if (localSession == null) | |
{ | |
authorizedSessions.put (remoteSession, jSessionId); | |
return true; | |
} | |
else if (localSession.equals (jSessionId) ) | |
{ | |
return true; | |
} | |
break; | |
} | |
} | |
} | |
return false; | |
} | |
/** | |
* | |
* @param request The servlet request we are processing | |
* @param response The servlet response we are creating | |
* @param chain The filter chain we are processing | |
* | |
* @exception IOException if an input/output error occurs | |
* @exception ServletException if a servlet error occurs | |
*/ | |
@Override | |
public void doFilter (ServletRequest request, ServletResponse response, | |
FilterChain chain) | |
throws IOException, ServletException | |
{ | |
if (debug) | |
{ | |
log ("AuthFilter:doFilter()"); | |
} | |
// Create wrappers for the request and response objects. | |
// Using these, you can extend the capabilities of the | |
// request and response, for example, allow setting parameters | |
// on the request before sending the request to the rest of the filter chain, | |
// or keep track of the cookies that are set on the response. | |
// | |
// Caveat: some servers do not handle wrappers very well for forward or | |
// include requests. | |
RequestWrapper wrappedRequest = new RequestWrapper ((HttpServletRequest) request); | |
ResponseWrapper wrappedResponse = new ResponseWrapper ((HttpServletResponse) response); | |
Map<String, String> authorizedSessions = (Map<String, String>) wrappedRequest.getServletContext ().getAttribute (AuthManagerServlet.class.getPackage ().getName () + "." + AuthManagerServlet.class.getName () + ".authorizedSessions"); | |
if (authorizedSessions == null) | |
{ | |
wrappedResponse.sendError (HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); | |
return; | |
} | |
if (!validateSession (wrappedRequest, authorizedSessions)) | |
{ | |
wrappedResponse.sendError (HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); | |
return; | |
} | |
Throwable problem = null; | |
try | |
{ | |
chain.doFilter (wrappedRequest, wrappedResponse); | |
} | |
catch (IOException | ServletException t) | |
{ | |
// If an exception is thrown somewhere down the filter chain, | |
// we still want to execute our after processing, and then | |
// rethrow the problem after that. | |
problem = t; | |
} | |
// If there was a problem, we want to rethrow it if it is | |
// a known type, otherwise log it. | |
if (problem != null) | |
{ | |
if (problem instanceof ServletException) | |
{ | |
throw (ServletException) problem; | |
} | |
if (problem instanceof IOException) | |
{ | |
throw (IOException) problem; | |
} | |
sendProcessingError (problem, response); | |
} | |
} | |
/** | |
* Return the filter configuration object for this filter. | |
*/ | |
public FilterConfig getFilterConfig () | |
{ | |
return (this.filterConfig); | |
} | |
/** | |
* Set the filter configuration object for this filter. | |
* | |
* @param filterConfig The filter configuration object | |
*/ | |
public void setFilterConfig (FilterConfig filterConfig) | |
{ | |
this.filterConfig = filterConfig; | |
} | |
/** | |
* Destroy method for this filter | |
*/ | |
@Override | |
public void destroy () | |
{ | |
} | |
/** | |
* Init method for this filter | |
*/ | |
@Override | |
public void init (FilterConfig filterConfig) | |
{ | |
this.filterConfig = filterConfig; | |
if (filterConfig != null) | |
{ | |
if (debug) | |
{ | |
log ("AuthFilter: Initializing filter"); | |
} | |
} | |
} | |
/** | |
* Return a String representation of this object. | |
*/ | |
@Override | |
public String toString () | |
{ | |
if (filterConfig == null) | |
{ | |
return ("AuthFilter()"); | |
} | |
StringBuilder sb = new StringBuilder ("AuthFilter("); | |
sb.append (filterConfig); | |
sb.append (")"); | |
return (sb.toString ()); | |
} | |
private void sendProcessingError (Throwable t, ServletResponse response) | |
{ | |
String stackTrace = getStackTrace (t); | |
if (stackTrace != null && !stackTrace.equals ("")) | |
{ | |
try | |
{ | |
response.setContentType ("text/html"); | |
try (PrintStream ps = new PrintStream (response.getOutputStream ()); PrintWriter pw = new PrintWriter (ps)) | |
{ | |
pw.print ("\n\nError\n\n\n"); //NOI18N | |
// PENDING! Localize this for next official release | |
pw.print ("</pre><h1>The resource did not process correctly</h1><pre>\n\n"); | |
pw.print (stackTrace); | |
pw.print ("\n"); | |
//NOI18N | |
} | |
response.getOutputStream ().close (); | |
} | |
catch (Exception ex) | |
{ | |
} | |
} | |
else | |
{ | |
try | |
{ | |
try (PrintStream ps = new PrintStream (response.getOutputStream ())) | |
{ | |
t.printStackTrace (ps); | |
} | |
response.getOutputStream ().close (); | |
} | |
catch (Exception ex) | |
{ | |
} | |
} | |
} | |
public static String getStackTrace (Throwable t) | |
{ | |
String stackTrace = null; | |
try | |
{ | |
StringWriter sw = new StringWriter (); | |
PrintWriter pw = new PrintWriter (sw); | |
t.printStackTrace (pw); | |
pw.close (); | |
sw.close (); | |
stackTrace = sw.getBuffer ().toString (); | |
} | |
catch (Exception ex) | |
{ | |
} | |
return stackTrace; | |
} | |
public void log (String msg) | |
{ | |
filterConfig.getServletContext ().log (msg); | |
} | |
/** | |
* This request wrapper class extends the support class HttpServletRequestWrapper, which implements all the methods in the | |
* HttpServletRequest interface, as delegations to the wrapped request. You only need to override the methods that you need to change. You | |
* can get access to the wrapped request using the method getRequest() | |
*/ | |
class RequestWrapper extends HttpServletRequestWrapper | |
{ | |
public RequestWrapper (HttpServletRequest request) | |
{ | |
super (request); | |
} | |
// You might, for example, wish to add a setParameter() method. To do this | |
// you must also override the getParameter, getParameterValues, getParameterMap, | |
// and getParameterNames methods. | |
protected HashMap localParams = null; | |
public void setParameter (String name, String[] values) | |
{ | |
if (debug) | |
{ | |
System.out.println ("AuthFilter::setParameter(" + name + "=" + values + ")" + " localParams = " + localParams); | |
} | |
if (localParams == null) | |
{ | |
localParams = new HashMap (); | |
// Copy the parameters from the underlying request. | |
Map wrappedParams = getRequest ().getParameterMap (); | |
Set keySet = wrappedParams.keySet (); | |
for (Iterator it = keySet.iterator (); it.hasNext ();) | |
{ | |
Object key = it.next (); | |
Object value = wrappedParams.get (key); | |
localParams.put (key, value); | |
} | |
} | |
localParams.put (name, values); | |
} | |
@Override | |
public String getParameter (String name) | |
{ | |
if (debug) | |
{ | |
System.out.println ("AuthFilter::getParameter(" + name + ") localParams = " + localParams); | |
} | |
if (localParams == null) | |
{ | |
return getRequest ().getParameter (name); | |
} | |
Object val = localParams.get (name); | |
if (val instanceof String) | |
{ | |
return (String) val; | |
} | |
if (val instanceof String[]) | |
{ | |
String[] values = (String[]) val; | |
return values[0]; | |
} | |
return (val == null ? null : val.toString ()); | |
} | |
@Override | |
public String[] getParameterValues (String name) | |
{ | |
if (debug) | |
{ | |
System.out.println ("AuthFilter::getParameterValues(" + name + ") localParams = " + localParams); | |
} | |
if (localParams == null) | |
{ | |
return getRequest ().getParameterValues (name); | |
} | |
return (String[]) localParams.get (name); | |
} | |
@Override | |
public Enumeration getParameterNames () | |
{ | |
if (debug) | |
{ | |
System.out.println ("AuthFilter::getParameterNames() localParams = " + localParams); | |
} | |
if (localParams == null) | |
{ | |
return getRequest ().getParameterNames (); | |
} | |
return Collections.enumeration (localParams.keySet ()); | |
} | |
@Override | |
public Map getParameterMap () | |
{ | |
if (debug) | |
{ | |
System.out.println ("AuthFilter::getParameterMap() localParams = " + localParams); | |
} | |
if (localParams == null) | |
{ | |
return getRequest ().getParameterMap (); | |
} | |
return localParams; | |
} | |
} | |
/** | |
* This response wrapper class extends the support class HttpServletResponseWrapper, which implements all the methods in the | |
* HttpServletResponse interface, as delegations to the wrapped response. You only need to override the methods that you need to change. | |
* You can get access to the wrapped response using the method getResponse() | |
*/ | |
class ResponseWrapper extends HttpServletResponseWrapper | |
{ | |
public ResponseWrapper (HttpServletResponse response) | |
{ | |
super (response); | |
} | |
// You might, for example, wish to know what cookies were set on the response | |
// as it went throught the filter chain. Since HttpServletRequest doesn't | |
// have a get cookies method, we will need to store them locally as they | |
// are being set. | |
/* | |
* protected Vector cookies = null; | |
* | |
* // Create a new method that doesn't exist in HttpServletResponse public Enumeration getCookies() { if (cookies == null) cookies = | |
* new Vector(); return cookies.elements(); } | |
* | |
* // Override this method from HttpServletResponse to keep track // of cookies locally as well as in the wrapped response. public void | |
* addCookie (Cookie cookie) { if (cookies == null) cookies = new Vector(); cookies.add(cookie); | |
* ((HttpServletResponse)getResponse()).addCookie(cookie); } | |
*/ | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class AuthManagerServlet extends HttpServlet | |
{ | |
public static final String ENCRYPTION_KEY = "ENCRYPTION_KEY"; | |
private Map<String, String> authorizedSessions = new HashMap<> (); | |
private String encryptionKey, initialVector = null; | |
private Timer timer = new Timer (true); | |
private enum Operations | |
{ | |
LOGIN, LOGOUT | |
} | |
/** | |
* Processes requests for both HTTP | |
* <code>GET</code> and | |
* <code>POST</code> methods. | |
* | |
* @param request servlet request | |
* @param response servlet response | |
* @throws ServletException if a servlet-specific error occurs | |
* @throws IOException if an I/O error occurs | |
*/ | |
protected void processRequest (HttpServletRequest request, HttpServletResponse response) | |
throws ServletException, IOException | |
{ | |
response.setContentType ("text/html;charset=UTF-8"); | |
PrintWriter out = response.getWriter (); | |
String message = null; | |
try | |
{ | |
String encData = request.getParameter ("data"); | |
if (encData == null) | |
{ | |
message = "Operation failed. Data cannot be null."; | |
response.sendError (HttpServletResponse.SC_UNAUTHORIZED, message); | |
} | |
else | |
{ | |
String params = Transcoder.decrypt (encData, initialVector, encryptionKey); | |
StringTokenizer st = new StringTokenizer (params, "&="); | |
final Map<String, String> paramMap = new HashMap<> (); | |
while (st.hasMoreTokens ()) | |
{ | |
String name = st.nextToken (); | |
String value = st.nextToken (); | |
paramMap.put (name, value); | |
} | |
Operations ops; | |
try | |
{ | |
ops = Operations.valueOf (paramMap.get ("op").toUpperCase ()); | |
switch (ops) | |
{ | |
case LOGIN: | |
authorizedSessions.put (paramMap.get ("session_id"), null); | |
int timeout = Integer.parseInt (paramMap.get ("timeout")); | |
//Timeout is received with each auth request, but is set globally for all future sessions. | |
request.getServletContext ().setAttribute (getClass ().getPackage ().getName () + "." + getClass ().getName () + ".sessionTimeout", timeout); | |
message = "Login successful."; | |
break; | |
case LOGOUT: | |
authorizedSessions.remove (paramMap.get ("session_id")); | |
message = "Logout successful."; | |
break; | |
} | |
} | |
catch (IllegalArgumentException e) | |
{ | |
message = "Operation failed. Invalid op."; | |
response.sendError (HttpServletResponse.SC_UNAUTHORIZED, message); | |
} | |
} | |
} | |
finally | |
{ | |
out.println (message); | |
out.close (); | |
} | |
} | |
// | |
/** | |
* Handles the HTTP | |
* <code>GET</code> method. | |
* | |
* @param request servlet request | |
* @param response servlet response | |
* @throws ServletException if a servlet-specific error occurs | |
* @throws IOException if an I/O error occurs | |
*/ | |
@Override | |
protected void doGet (HttpServletRequest request, HttpServletResponse response) | |
throws ServletException, IOException | |
{ | |
processRequest (request, response); | |
} | |
/** | |
* Handles the HTTP | |
* <code>POST</code> method. | |
* | |
* @param request servlet request | |
* @param response servlet response | |
* @throws ServletException if a servlet-specific error occurs | |
* @throws IOException if an I/O error occurs | |
*/ | |
@Override | |
protected void doPost (HttpServletRequest request, HttpServletResponse response) | |
throws ServletException, IOException | |
{ | |
processRequest (request, response); | |
} | |
/** | |
* Returns a short description of the servlet. | |
* | |
* @return a String containing servlet description | |
*/ | |
@Override | |
public String getServletInfo () | |
{ | |
return "Simple Authentication Manager Servlet, based on background info recieved from authorized servers."; | |
}// | |
@Override | |
public void init (ServletConfig config) throws ServletException | |
{ | |
super.init (config); | |
ServletContext context = config.getServletContext (); | |
context.setAttribute (getClass ().getPackage ().getName () + "." + getClass ().getName () + ".authorizedSessions", authorizedSessions); | |
encryptionKey = context.getInitParameter (ENCRYPTION_KEY); | |
if (encryptionKey == null) | |
{ | |
Logger.getLogger (getClass ().getName ()).log (Level.SEVERE, "Error!! Encryption key not found."); | |
} | |
try | |
{ | |
initialVector = Transcoder.md5 (Transcoder.md5 (encryptionKey)).substring (0, 16); | |
} | |
catch (NoSuchAlgorithmException ex) | |
{ | |
Logger.getLogger (getClass ().getName ()).log (Level.SEVERE, null, ex); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Snippets from the main module file. One problem with Drupal (as of 7.14) is that the session id is not available at the time the user login hook is fired. | |
* To get around this limitation, I need to define my own table for tracking sessions and mapping them to user ids. | |
* The init hook, which is one of the first to fire on every page load, looks for entries in the table with blank session ids and does the requisite post-login processing. | |
* As a consequence of introducing this additional table, some additional logic is required to update its data on each event. | |
**/ | |
/** | |
* Implements hook_user_logout(). | |
*/ | |
function birt_reports_user_logout($account) { | |
db_delete('birt_reports_sessions') | |
->condition('uid', $account->uid) | |
->condition('sid', $account->sid) | |
->execute(); | |
$birt_reports_auth_sessions = cache_get('birt_reports_auth_sessions'); | |
if (!empty($birt_reports_auth_sessions)) { | |
unset($birt_reports_auth_sessions->data[$account->sid]); | |
cache_set('birt_reports_auth_sessions', $birt_reports_auth_sessions->data, 'cache', CACHE_PERMANENT); | |
} | |
_birt_reports_report_server_auth($account->sid, 'logout'); | |
} | |
/** | |
* Implements hook_user_login(). | |
*/ | |
function birt_reports_user_login(&$edit, $account) { | |
//Session ID is not yet present. So using roundabout method. | |
if (user_access('access report servers', $account)) { | |
db_insert('birt_reports_sessions') | |
->fields(array('uid' => $account->uid)) | |
->execute(); | |
} | |
} | |
function _birt_reports_report_server_auth($sid, $op, $timeout = 600) { | |
$params = "session_id=$sid&op=$op&timeout=$timeout"; | |
//Every time a field instance is created/updated, its data is also saved to the variables table for easy retrieval later on. | |
$encryption_keys = variable_get('birt_reports_encryption_keys', array()); | |
$report_servers = variable_get('birt_reports_active_report_servers', array()); | |
$session_servlets = variable_get('birt_reports_session_servlets', array()); | |
$options = array( | |
'method' => 'POST', | |
'headers' => array('Content-Type' => 'application/x-www-form-urlencoded'), | |
); | |
//Inform all registered report servers of new event. | |
foreach ($report_servers as $id => $server) { | |
$key = $encryption_keys[$id]; | |
if (empty($key)) { | |
watchdog('birt_reports', 'Encryption key not set for report server @server. Skipping authentication.', array('@server' => $server), WATCHDOG_WARNING); | |
continue; | |
} | |
$servlet = empty($session_servlets[$id]) ? 'smanage' : $session_servlets[$id]; | |
$url = $server . "/$servlet"; | |
//AES 128 bit encryption requires the initial vector to be 16 chars long. | |
//This is strictly enforced in Java, though not in PHP. | |
$iv = substr(md5(md5($key)), 0, 16); | |
$data = _birt_reports_encrypt($params, $iv, $key); | |
$options['data'] = 'data=' . urlencode($data); | |
// dpm ($data); | |
$result = drupal_http_request($url, $options); | |
if (isset($result->error)) { | |
watchdog('birt_reports', 'Error logging in/out from report server @server. Error is: @error', array('@server' => $server, '@error' => "$result->code $result->error"), WATCHDOG_ERROR); | |
} | |
else { | |
watchdog('birt_reports', 'Successful auth transaction with report server @server. Message is: @message', array('@server' => $server, '@message' => "$result->status_message"), WATCHDOG_INFO); | |
} | |
} | |
} | |
function _birt_reports_encrypt($message, $initialVector, $secretKey) { | |
return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, md5($secretKey), $message, MCRYPT_MODE_CFB, $initialVector)); | |
} | |
/** | |
* Implements hook_init(). | |
*/ | |
function birt_reports_init() { | |
global $user; | |
if (user_access('access report servers')) { | |
$birt_reports_auth_sessions = cache_get('birt_reports_auth_sessions'); | |
if (empty($birt_reports_auth_sessions)) { | |
$birt_reports_auth_sessions = new stdClass(); | |
$birt_reports_auth_sessions->data = array(); | |
} | |
if (!in_array($user->sid, $birt_reports_auth_sessions->data)) { | |
$result = db_select('birt_reports_sessions', 'b') | |
->fields('b', array('uid', 'sid')) | |
->condition('b.uid', $user->uid, '=') | |
->condition('b.sid', '0', '=') | |
->execute() | |
->fetchObject(); | |
$uid = $result->uid; | |
if ($uid) { | |
db_update('birt_reports_sessions') | |
->fields(array('sid' => $user->sid)) | |
->condition('uid', $uid) | |
->condition('sid', '0') | |
->execute(); | |
$timeout = ini_get('session.cookie_lifetime'); | |
if (!is_numeric($timeout) || ($timeout < 0)) { $timeout = 600; } _birt_reports_report_server_auth($user->sid, 'login', $timeout); | |
} | |
$birt_reports_auth_sessions->data[$user->sid] = $user->sid; | |
cache_set('birt_reports_auth_sessions', $birt_reports_auth_sessions->data, 'cache', CACHE_PERMANENT); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@WebListener () | |
public class SessionLifecycleListener implements HttpSessionListener | |
{ | |
@Override | |
public void sessionCreated (HttpSessionEvent hse) | |
{ | |
int sessionTimeout = (int) hse.getSession ().getServletContext ().getAttribute (AuthManagerServlet.class.getPackage ().getName () + "." + AuthManagerServlet.class.getName () + ".sessionTimeout"); | |
if (sessionTimeout <= 0) | |
{ | |
sessionTimeout = 600; | |
} | |
hse.getSession ().setMaxInactiveInterval (sessionTimeout); | |
} | |
@Override | |
public void sessionDestroyed (HttpSessionEvent hse) | |
{ | |
Map<String, String> authorizedSessions = (Map<String, String>) hse.getSession ().getServletContext ().getAttribute (AuthManagerServlet.class.getPackage ().getName () + "." + AuthManagerServlet.class.getName () + ".authorizedSessions"); | |
String jSessionId = hse.getSession ().getId (); | |
Collection values = authorizedSessions.values (); | |
for (Iterator i = values.iterator (); i.hasNext ();) | |
{ | |
String value = i.next (); | |
if (jSessionId.equals (value)) | |
{ | |
authorizedSessions.remove (value); | |
break; | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Transcoder | |
{ | |
private Transcoder () | |
{ | |
} | |
public static String md5 (String input) throws NoSuchAlgorithmException | |
{ | |
MessageDigest md = MessageDigest.getInstance ("MD5"); | |
byte[] messageDigest = md.digest (input.getBytes ()); | |
BigInteger number = new BigInteger (1, messageDigest); | |
return number.toString (16); | |
} | |
public static String decrypt (String encryptedData, String initialVectorString, String secretKey) | |
{ | |
String decryptedData = null; | |
try | |
{ | |
SecretKeySpec skeySpec = new SecretKeySpec (md5 (secretKey).getBytes (), "AES"); | |
IvParameterSpec initialVector = new IvParameterSpec (initialVectorString.getBytes ()); | |
Cipher cipher = Cipher.getInstance ("AES/CFB8/NoPadding"); | |
cipher.init (Cipher.DECRYPT_MODE, skeySpec, initialVector); | |
byte[] encryptedByteArray = (new org.apache.commons.codec.binary.Base64 ()).decode (encryptedData.getBytes ()); | |
byte[] decryptedByteArray = cipher.doFinal (encryptedByteArray); | |
decryptedData = new String (decryptedByteArray, "UTF-8"); | |
} | |
catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException | UnsupportedEncodingException e) | |
{ | |
Logger.getLogger (Transcoder.class.getName ()).log (Level.SEVERE, "Problem decrypting the data", e); | |
} | |
return decryptedData; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- | |
Report resources directory for preview. Defaults to ${birt home} | |
--> | |
<context-param> | |
<param-name>BIRT_VIEWER_WORKING_FOLDER</param-name> | |
<param-value>report</param-value> | |
</context-param> | |
<context-param> | |
<description>The secret key used to encrypt/decrypt informations between servers and browsers. Must never be transmitted!</description> | |
<param-name>ENCRYPTION_KEY</param-name> | |
<param-value>{your encryption key}</param-value> | |
</context-param> | |
<filter> | |
<filter-name>AuthFilter</filter-name> | |
<filter-class>{package.path}.AuthFilter</filter-class> | |
</filter> | |
<filter-mapping> | |
<filter-name>AuthFilter</filter-name> | |
<servlet-name>EngineServlet</servlet-name> | |
</filter-mapping> | |
<filter-mapping> | |
<filter-name>AuthFilter</filter-name> | |
<servlet-name>ViewerServlet</servlet-name> | |
</filter-mapping> | |
<servlet> | |
<servlet-name>AuthManagerServlet</servlet-name> | |
<servlet-class>{package.path}.AuthManagerServlet</servlet-class> | |
</servlet> | |
<servlet-mapping> | |
<servlet-name>AuthManagerServlet</servlet-name> | |
<url-pattern>/smanage</url-pattern> | |
</servlet-mapping> | |
<session-config> | |
<session-timeout>10</session-timeout> | |
</session-config> | |
<listener> | |
<listener-class>{package.path}.SessionLifecycleListener</listener-class> | |
</listener> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Full tutorial at http://adityamukho.github.io/categories/BIRT%20SSO%20Series/