View Javadoc
1   /*
2    * This file is part of ***  M y C o R e  ***
3    * See http://www.mycore.de/ for details.
4    *
5    * MyCoRe is free software: you can redistribute it and/or modify
6    * it under the terms of the GNU General Public License as published by
7    * the Free Software Foundation, either version 3 of the License, or
8    * (at your option) any later version.
9    *
10   * MyCoRe is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   *
15   * You should have received a copy of the GNU General Public License
16   * along with MyCoRe.  If not, see <http://www.gnu.org/licenses/>.
17   */
18  
19  package org.mycore.user2.login;
20  
21  import org.apache.logging.log4j.LogManager;
22  import org.apache.logging.log4j.Logger;
23  import org.jasig.cas.client.authentication.AttributePrincipal;
24  import org.jasig.cas.client.validation.Assertion;
25  import org.jasig.cas.client.validation.Cas20ProxyTicketValidator;
26  import org.mycore.common.MCRSessionMgr;
27  import org.mycore.common.config.MCRConfiguration2;
28  import org.mycore.frontend.servlets.MCRServlet;
29  import org.mycore.frontend.servlets.MCRServletJob;
30  import org.mycore.user2.MCRUser;
31  import org.mycore.user2.MCRUser2Constants;
32  import org.mycore.user2.MCRUserManager;
33  
34  import jakarta.servlet.ServletException;
35  import jakarta.servlet.http.HttpServletRequest;
36  import jakarta.servlet.http.HttpServletResponse;
37  
38  /**
39   * Login user with JA-SIG Central Authentication Service (CAS).
40   * The servlet validates the ticket returned from CAS and
41   * builds a User object to login to the current session.
42   * 
43   * For /servlets/MCRCASServlet, a authentication filter must be defined
44   * in web.xml. The following properties must be configured in 
45   * mycore.properties:
46   * 
47   *  The URL of the CAS Client Servlet:
48   * MCR.user2.CAS.ClientURL=http://localhost:8291/servlets/MCRCASServlet
49   *
50   * The Base URL of the CAS Server
51   * MCR.user2.CAS.ServerURL=https://cas.uni-duisburg-essen.de/cas
52   *
53   * The realm the CAS Server authenticates for, as in realms.xml
54   * MCR.user2.CAS.RealmID=ude
55   *
56   * Configure store of trusted SSL (https) server certificates
57   * MCR.user2.CAS.SSL.TrustStore=/path/to/java/lib/security/cacerts
58   * MCR.user2.CAS.SSL.TrustStore.Password=changeit
59   * 
60   * After successful login, MCRCASServlet queries an LDAP server for
61   * the user's properties.
62   *
63   * @author Frank L\u00fctzenkirchen
64   */
65  public class MCRCASServlet extends MCRServlet {
66      private static final long serialVersionUID = 1L;
67  
68      /** The logger */
69      private static Logger LOGGER = LogManager.getLogger();
70  
71      /** The URL of THIS servlet */
72      private String clientURL;
73  
74      /** The base URL of the CAS Server */
75      private String serverURL;
76  
77      /** The realm the CAS Server authenticates for, as in realms.xml */
78      private String realmID;
79  
80      @Override
81      public void init() throws ServletException {
82          super.init();
83  
84          clientURL = MCRConfiguration2.getStringOrThrow(MCRUser2Constants.CONFIG_PREFIX + "CAS.ClientURL");
85          serverURL = MCRConfiguration2.getStringOrThrow(MCRUser2Constants.CONFIG_PREFIX + "CAS.ServerURL");
86          realmID = MCRConfiguration2.getStringOrThrow(MCRUser2Constants.CONFIG_PREFIX + "CAS.RealmID");
87  
88          // Set properties to enable SSL connection to CAS and accept certificates  
89          String trustStore = MCRConfiguration2.getStringOrThrow(MCRUser2Constants.CONFIG_PREFIX + "CAS.SSL.TrustStore");
90          String trustStorePassword = MCRConfiguration2
91              .getStringOrThrow(MCRUser2Constants.CONFIG_PREFIX + "CAS.SSL.TrustStore.Password");
92  
93          System.setProperty("javax.net.ssl.trustStore", trustStore);
94          System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword);
95      }
96  
97      public void doGetPost(MCRServletJob job) throws Exception {
98          HttpServletRequest req = job.getRequest();
99          HttpServletResponse res = job.getResponse();
100 
101         String ticket = req.getParameter("ticket");
102         if ((ticket == null) || (ticket.trim().length() == 0)) {
103             res.sendError(HttpServletResponse.SC_BAD_REQUEST);
104             return;
105         }
106 
107         // Validate ticket at CAS server
108         Cas20ProxyTicketValidator sv = new Cas20ProxyTicketValidator(serverURL);
109         sv.setAcceptAnyProxy(true);
110         Assertion a = sv.validate(ticket, clientURL);
111         AttributePrincipal principal = a.getPrincipal();
112 
113         // Get user name logged in
114         String userName = principal.getName();
115         LOGGER.info("Login {}", userName);
116 
117         MCRUser user;
118         boolean userExists = MCRUserManager.exists(userName, realmID);
119         if (userExists) {
120             user = MCRUserManager.getUser(userName, realmID);
121         } else {
122             user = new MCRUser(userName, realmID);
123         }
124 
125         // Get user properties from LDAP server
126         boolean userChanged = MCRLDAPClient.instance().updateUserProperties(user);
127         if (userChanged && userExists) {
128             MCRUserManager.updateUser(user);
129         }
130 
131         // Store login user in session and redirect browser to target url
132         MCRSessionMgr.getCurrentSession().setUserInformation(user);
133         // MCR-1154
134         req.changeSessionId();
135         MCRLoginServlet.redirect(res);
136     }
137 }