Index: lams_central/src/java/org/lamsfoundation/lams/web/LoginRequestServlet.java
===================================================================
diff -u
--- lams_central/src/java/org/lamsfoundation/lams/web/LoginRequestServlet.java (revision 0)
+++ lams_central/src/java/org/lamsfoundation/lams/web/LoginRequestServlet.java (revision 78963ed83cfe540006a5ad51066d03e15781ef5b)
@@ -0,0 +1,219 @@
+/**
+ * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * http://www.gnu.org/licenses/gpl.txt
+ */
+package org.lamsfoundation.lams.web;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.security.auth.login.FailedLoginException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import javax.sql.DataSource;
+
+import org.apache.log4j.Logger;
+import org.lamsfoundation.lams.integration.ExtCourseClassMap;
+import org.lamsfoundation.lams.integration.ExtServerOrgMap;
+import org.lamsfoundation.lams.integration.ExtUserUseridMap;
+import org.lamsfoundation.lams.integration.UserInfoFetchException;
+import org.lamsfoundation.lams.integration.security.AuthenticationException;
+import org.lamsfoundation.lams.integration.security.Authenticator;
+import org.lamsfoundation.lams.integration.service.IntegrationService;
+import org.lamsfoundation.lams.integration.util.LoginRequestDispatcher;
+import org.lamsfoundation.lams.usermanagement.Organisation;
+import org.lamsfoundation.lams.usermanagement.Role;
+import org.lamsfoundation.lams.usermanagement.User;
+import org.lamsfoundation.lams.usermanagement.UserOrganisation;
+import org.lamsfoundation.lams.usermanagement.UserOrganisationRole;
+import org.lamsfoundation.lams.usermanagement.service.IUserManagementService;
+import org.lamsfoundation.lams.web.session.SessionManager;
+import org.lamsfoundation.lams.web.util.AttributeNames;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
+/**
+ * The LoginRequestServlet handles login request by an integrated external
+ * system. This servlet checks for the UserId, Timestamp, Hash and ServerId if
+ * it's valid it fetch the password from database and pass it to
+ * j_security_check for authentication
+ *
+ * @author Fei Yang, Anthony Xiao
+ */
+@SuppressWarnings("serial")
+public class LoginRequestServlet extends HttpServlet {
+
+ private static Logger log = Logger.getLogger(LoginRequestServlet.class);
+
+ private static IntegrationService integrationService = null;
+
+ private static final String JNDI_DATASOURCE = "java:/jdbc/lams-ds";
+
+ private static final String PASSWORD_QUERY = "select password from lams_user where login=?";
+
+ /**
+ * The doGet method of the servlet.
+ *
+ * This method is called when a form has its tag value method equals to get.
+ *
+ * @param request
+ * the request send by the client to the server
+ * @param response
+ * the response send by the server to the client
+ * @throws ServletException
+ * if an error occurred
+ * @throws IOException
+ * if an error occurred
+ */
+ public void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ // create http session required by the valve
+ // since valve can't create session
+ /*HttpSession hses = request.getSession();
+ if(hses!=null) hses.invalidate();
+ HttpSession sharedsession = SessionManager.getSession();
+ if(sharedsession!=null) sharedsession.invalidate();*/
+ HttpSession hses = request.getSession(true);
+
+ String extUsername = request.getParameter(LoginRequestDispatcher.PARAM_USER_ID);
+ String serverId = request.getParameter(LoginRequestDispatcher.PARAM_SERVER_ID);
+ String extCourseId = request.getParameter(LoginRequestDispatcher.PARAM_COURSE_ID);
+ String timestamp = request.getParameter(LoginRequestDispatcher.PARAM_TIMESTAMP);
+ String hash = request.getParameter(LoginRequestDispatcher.PARAM_HASH);
+ String method = request.getParameter(LoginRequestDispatcher.PARAM_METHOD);
+ String countryIsoCode = request.getParameter(LoginRequestDispatcher.PARAM_COUNTRY);
+ String langIsoCode = request.getParameter(LoginRequestDispatcher.PARAM_LANGUAGE);
+
+ if (extUsername == null || method == null || serverId == null || timestamp == null
+ || hash == null || extCourseId == null) {
+ response.sendError(HttpServletResponse.SC_BAD_REQUEST,
+ "Login Failed - login parameters missing");
+ return;
+ }
+ ExtServerOrgMap serverMap = getService().getExtServerOrgMap(serverId);
+
+ try {
+ ExtUserUseridMap userMap = getService().getExtUserUseridMap(serverMap, extUsername);
+ Authenticator.authenticate(serverMap, timestamp, extUsername, method, hash);
+ ExtCourseClassMap orgMap = getService().getExtCourseClassMap(serverMap, userMap, extCourseId, countryIsoCode, langIsoCode);
+ User user = userMap.getUser();
+ String login = user.getLogin();
+ //was using hses.inNew() API to check if the external user has logged in yet,
+ // but it seems not working. The "extUser" attribute works as a flag to indicate
+ // if the user has logged in
+ String loginRequestUsername = (String)hses.getAttribute("extUser");
+ if(loginRequestUsername != null && loginRequestUsername.equals(login)){
+ String url = LoginRequestDispatcher.getRequestURL(request);
+ log.debug("redirect url - "+url);
+ response.sendRedirect(response.encodeRedirectURL(url));
+ return;
+ } else if(loginRequestUsername != null && !loginRequestUsername.equals(login)){
+ hses.invalidate();
+ hses = request.getSession(true);
+ } else if(request.getRemoteUser() != null && loginRequestUsername == null){
+ hses.invalidate();
+ hses = request.getSession(true);
+ }
+ Organisation org = orgMap.getOrganisation();
+ IUserManagementService userManagementService = integrationService.getService();
+ UserOrganisation uo = userManagementService.getUserOrganisation(user.getUserId(), org.getOrganisationId());
+ //COURSE_MANAGER role is to enable user to see the course's workspace folder
+ Integer[] roleIds = new Integer[]{Role.ROLE_AUTHOR,Role.ROLE_COURSE_MANAGER,Role.ROLE_LEARNER};
+ //we have to assign all the roles to the external user here, because once the user logged in, the roles
+ //are cached in JBoss, all the calls of request.isUserInRole() will be based on the cached roles
+ Map properties = new HashMap();
+ properties.put("userOrganisation.userOrganisationId", uo.getUserOrganisationId());
+ for(Integer roleId : roleIds){
+ properties.put("role.roleId", roleId);
+ List list = userManagementService.findByProperties(UserOrganisationRole.class, properties);
+ if(list==null || list.size()==0){
+ UserOrganisationRole uor = new UserOrganisationRole(uo, (Role)userManagementService.findById(Role.class, roleId));
+ userManagementService.save(uor);
+ }
+ }
+ log.debug("Session Id - "+hses.getId());
+ // connect to DB and get password here
+ String pass = getUserPassword(userMap.getUser().getLogin());
+ // should post the parameters back so it's little more secure,
+ // but forward doesn't work, use this until a better method is found
+ hses.setAttribute("extUser", login);
+ hses.setAttribute(AttributeNames.USER, user.getUserDTO());
+ response.sendRedirect("j_security_check?j_username=" + login + "&j_password=" + pass);
+ } catch (AuthenticationException e) {
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
+ "Login Failed - authentication error");
+ } catch (UserInfoFetchException e) {
+ response.sendError(HttpServletResponse.SC_BAD_GATEWAY,
+ "Login Failed - failed to fetch user info from the third party server");
+ } catch (FailedLoginException e) {
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
+ "Login Failed - user was not found");
+ } catch (NamingException e) {
+ response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
+ } catch (SQLException e) {
+ response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
+ }
+ }
+
+ // using JDBC connection to prevent the caching of passwords by hibernate
+ private String getUserPassword(String username) throws FailedLoginException, NamingException,
+ SQLException {
+ InitialContext ctx = new InitialContext();
+
+ DataSource ds = (DataSource) ctx.lookup(JNDI_DATASOURCE);
+ Connection conn = null;
+ String password = null;
+ try {
+ conn = ds.getConnection();
+ PreparedStatement ps = conn.prepareStatement(PASSWORD_QUERY);
+ ps.setString(1, username);
+ ResultSet rs = ps.executeQuery();
+
+ // check if there is any result
+ if (rs.next() == false)
+ throw new FailedLoginException("invalid username");
+
+ password = rs.getString(1);
+ rs.close();
+ } finally {
+ if (conn != null && !conn.isClosed())
+ conn.close();
+ }
+ return password;
+ }
+
+ private IntegrationService getService() {
+ if (integrationService == null) {
+ integrationService = (IntegrationService) WebApplicationContextUtils
+ .getRequiredWebApplicationContext(getServletContext()).getBean(
+ "integrationService");
+ }
+ return integrationService;
+ }
+}