Author: taylor
Date: Mon May 6 00:29:49 2019
New Revision: 1858717
URL: http://svn.apache.org/viewvc?rev=1858717&view=rev
Log:
JS2-1368: RememberMe Login Filter, contribution from Giacomo Morri
Added:
portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/security/impl/RememberMePortalFilter.java
Added:
portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/security/impl/RememberMePortalFilter.java
URL:
http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/security/impl/RememberMePortalFilter.java?rev=1858717&view=auto
==============================================================================
---
portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/security/impl/RememberMePortalFilter.java
(added)
+++
portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/security/impl/RememberMePortalFilter.java
Mon May 6 00:29:49 2019
@@ -0,0 +1,413 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jetspeed.security.impl;
+
+import org.apache.commons.lang.time.DateUtils;
+import org.apache.jetspeed.Jetspeed;
+import org.apache.jetspeed.PortalReservedParameters;
+import org.apache.jetspeed.administration.PortalAuthenticationConfiguration;
+import org.apache.jetspeed.administration.PortalConfiguration;
+import org.apache.jetspeed.audit.AuditActivity;
+import org.apache.jetspeed.cache.UserContentCacheManager;
+import org.apache.jetspeed.components.ComponentManager;
+import org.apache.jetspeed.container.session.PortalSessionValidationFilter;
+import org.apache.jetspeed.login.LoginConstants;
+import org.apache.jetspeed.login.filter.PortalRequestWrapper;
+import org.apache.jetspeed.security.AuthenticatedUser;
+import org.apache.jetspeed.security.AuthenticatedUserImpl;
+import org.apache.jetspeed.security.AuthenticationProvider;
+import org.apache.jetspeed.security.PasswordCredential;
+import org.apache.jetspeed.security.PasswordEncodingService;
+import org.apache.jetspeed.security.SecurityException;
+import org.apache.jetspeed.security.SubjectHelper;
+import org.apache.jetspeed.security.User;
+import org.apache.jetspeed.security.UserManager;
+
+import javax.naming.InitialContext;
+import javax.security.auth.Subject;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import javax.sql.DataSource;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URLDecoder;
+import java.security.Principal;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.util.Date;
+import java.util.Properties;
+
+/**
+ * @author Giacomo Morri
+ */
+public class RememberMePortalFilter implements Filter {
+
+ protected String guest = "guest";
+ protected FilterConfig fg = null;
+
+ protected PasswordEncodingService pes;
+ protected UserManager userManager;
+ protected AuditActivity audit;
+ protected AuthenticationProvider authProvider;
+ protected PortalAuthenticationConfiguration authenticationConfiguration;
+ protected UserContentCacheManager userContentCacheManager;
+
+ protected String rememberMeCookieName = "js_at";
+
+ public void init(FilterConfig filterConfig) throws ServletException {
+ PortalConfiguration config = Jetspeed.getConfiguration();
+ if (config != null) {
+ guest = config.getString("default.user.principal");
+ rememberMeCookieName =
config.getString("rmpf.accesstoken.cookie.name");
+ }
+ fg = filterConfig;
+ // load components once
+ ComponentManager cm = Jetspeed.getComponentManager();
+ pes =
cm.lookupComponent("org.apache.jetspeed.security.PasswordEncodingService");
+ userManager =
cm.lookupComponent("org.apache.jetspeed.security.UserManager");
+ audit = cm.lookupComponent("org.apache.jetspeed.audit.AuditActivity");
+ authProvider =
cm.lookupComponent("org.apache.jetspeed.security.AuthenticationProvider");
+ authenticationConfiguration =
cm.lookupComponent("org.apache.jetspeed.administration.PortalAuthenticationConfiguration");
+ userContentCacheManager =
cm.lookupComponent("userContentCacheManager");
+ }
+
+ protected String getTokenFromCookie(HttpServletRequest request) {
+ String token = null;
+ //reading token from cookies
+ Cookie[] cookies = request.getCookies();
+ if (cookies != null) {
+ if (cookies.length > 0) {
+ for (Cookie c : cookies) {
+ if (c.getName().equals(rememberMeCookieName)) {
+ token = c.getValue();
+ break;
+ }
+ }
+ }
+ }
+ return token;
+ }
+
+ public void doFilter(ServletRequest sRequest,
+ ServletResponse sResponse, FilterChain filterChain)
+ throws IOException, ServletException {
+ if (sRequest instanceof HttpServletRequest) {
+ HttpServletRequest request = (HttpServletRequest) sRequest;
+ HttpSession httpSession =
PortalSessionValidationFilter.getValidSession(request);
+
+ String username = null;
+ String password = null;
+
+ String token = null;
+
+ //checking if a user is already authenticated
+ boolean goOn = false;
+ Subject actualSubject = (Subject)
request.getSession().getAttribute(PortalReservedParameters.SESSION_KEY_SUBJECT);
+ if (actualSubject != null) {
+ Principal principal =
SubjectHelper.getPrincipal(actualSubject, User.class);
+
+ if (principal == null ||
principal.getName().equals(this.guest)) {
+ goOn = true;
+ }
+ } else {
+ goOn = true;
+ }
+
+ if (goOn) {
+ token = getTokenFromCookie(request);
+ if (token != null) {
+ token = URLDecoder.decode(token, "UTF-8");
+
+ if (token != null) {
+ username = getUsernameFromAccessToken(token);
+
+ if (username != null) {
+ try {
+ User jetspeedUser =
userManager.getUser(username);
+ PasswordCredential psw =
userManager.getPasswordCredential(jetspeedUser);
+
+ if (psw != null) {
+
+ String pswencoded = psw.getPassword();
+
+ if (pswencoded != null) {
+ password =
pes.decode(jetspeedUser.getName(), pswencoded);
+ }
+ }
+
+ } catch (SecurityException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ }
+
+ if (username != null && password != null && goOn) {
+
+ AuthenticatedUser authUser = null;
+ try {
+ authUser = authProvider.authenticate(username, password);
+ } catch (SecurityException e) {
+ audit.logUserActivity(username, request.getRemoteAddr(),
AuditActivity.AUTHENTICATION_FAILURE, "PortalFilter");
+
request.getSession().setAttribute(LoginConstants.ERRORCODE,
LoginConstants.ERROR_INVALID_PASSWORD);
+ }
+ if (authUser != null) {
+ audit.logUserActivity(username, request.getRemoteAddr(),
AuditActivity.AUTHENTICATION_SUCCESS, "PortalFilter");
+ if
(authenticationConfiguration.isCreateNewSessionOnLogin() && httpSession != null
&& !httpSession.isNew()) {
+ request.getSession().invalidate();
+ } else {
+
userContentCacheManager.evictUserContentCache(username,
request.getSession().getId());
+ }
+ if (authUser.getUser() == null) {
+ try {
+ // load the user principals (roles, groups,
credentials)
+ User user = userManager.getUser(username);
+ if (user != null) {
+ authUser = new AuthenticatedUserImpl(user,
authUser.getPublicCredentials(), authUser.getPrivateCredentials());
+ }
+ } catch (SecurityException sex) {
+ // TODO: maybe some better handling required here
+ throw new ServletException(sex);
+ }
+ }
+ Subject subject;
+ try {
+ // default solution using the build-in UserManager
+ subject = userManager.getSubject(authUser);
+
+ // alternate DIY solution not using the build-in
UserManager:
+ //subject =
JetspeedSubjectFactory.createSubject(authUser.getUser(),authUser.getPrivateCredentials(),authUser.getPublicCredentials(),null);
+ } catch (SecurityException e) {
+ // TODO: maybe some better handling required here
+ throw new ServletException(e);
+ }
+ sRequest = wrapperRequest(request, subject,
authUser.getUser());
+
request.getSession().removeAttribute(LoginConstants.ERRORCODE);
+ HttpSession session = request.getSession(true);
+
session.setAttribute(PortalReservedParameters.SESSION_KEY_SUBJECT, subject);
+
+ //setting login by token attribute in request
+ // FIXME:
request.setAttribute(Constants.REQUEST_ATTRIBUTE_LOGIN_BY_TOKEN, "true");
+
+ //updating token expiration date (+6 months)
+ updateTokenExpDate(token);
+
+ } else {
+ audit.logUserActivity(username, request.getRemoteAddr(),
AuditActivity.AUTHENTICATION_FAILURE, "PortalFilter");
+
request.getSession().setAttribute(LoginConstants.ERRORCODE,
LoginConstants.ERROR_INVALID_PASSWORD);
+ }
+ } else {
+ Subject subject = (Subject)
request.getSession().getAttribute(PortalReservedParameters.SESSION_KEY_SUBJECT);
+ if (subject != null) {
+ Principal principal = SubjectHelper.getPrincipal(subject,
User.class);
+ if (principal != null &&
principal.getName().equals(this.guest)) {
+ } else {
+ sRequest = wrapperRequest(request, subject, principal);
+ }
+ }
+ }
+
+ }
+
+ if (filterChain != null) {
+ filterChain.doFilter(sRequest, sResponse);
+ }
+ }
+
+ /**
+ * This requires additional tables:
+ * user_token
+ * user
+ *
+ * @param token
+ * @return
+ */
+ private String getUsernameFromAccessToken(String token) {
+ String username = null;
+
+ Connection connection = null;
+ Statement stmt = null;
+ ResultSet result = null;
+
+ InitialContext ic;
+ try {
+
+ String userId = null;
+
+ // getting DataSource from Jetspeed
+ ic = new InitialContext();
+ DataSource ds = (DataSource)
ic.lookup("java:comp/env/jdbc/jetspeed");
+
+ if (ds != null) {
+ connection = ds.getConnection();
+ stmt = connection.createStatement();
+
+ result = stmt.executeQuery("SELECT id,userid,date_expiry FROM
user_token WHERE token_value= '" + token + "'");
+
+ int count = 1;
+ boolean isValid = false;
+ Date expDate = null;
+ String tokenId = null;
+
+ // only the first result is loaded
+ while (result.next() && count <= 1) {
+
+ tokenId = result.getString("id");
+ userId = result.getString("userid");
+ expDate = result.getDate("date_expiry");
+
+ count++;
+ }
+
+ result.close();
+
+ // check expiration date
+ if (expDate != null) {
+ Date actualDate = new Date();
+ if (actualDate.before(expDate)) {
+ isValid = true;
+ } else {
+ //token expired, delete it
+ stmt.executeUpdate("DELETE FROM user_token WHERE id=
'" + tokenId + "'");
+ }
+ }
+
+ if (userId != null && isValid) {
+
+ result = stmt.executeQuery("SELECT jetspeed_username FROM
user WHERE id= '" + userId + "'");
+
+ count = 1;
+
+ // only the first result is loaded
+ while (result.next() && count <= 1) {
+
+ username = result.getString("jetspeed_username");
+
+ count++;
+ }
+
+ result.close();
+
+ }
+
+ stmt.close();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ if (result != null)
+ result.close();
+
+ if (stmt != null)
+ stmt.close();
+
+ if (connection != null)
+ connection.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ return username;
+ }
+
+ private void updateTokenExpDate(String token) {
+
+ Connection connection = null;
+ Statement stmt = null;
+ ResultSet result = null;
+
+ InitialContext ic;
+ try {
+
+ // getting DataSource from Jetspeed
+ ic = new InitialContext();
+ DataSource ds = (DataSource)
ic.lookup("java:comp/env/jdbc/jetspeed");
+
+ if (ds != null) {
+ connection = ds.getConnection();
+ stmt = connection.createStatement();
+
+ result = stmt.executeQuery("SELECT id FROM user_token WHERE
token_value= '" + token + "'");
+
+ int count = 1;
+ String tokenId = null;
+
+ // only the first result is loaded
+ while (result.next() && count <= 1) {
+
+ tokenId = result.getString("id");
+
+ count++;
+ }
+
+ result.close();
+
+ // check expiration date
+ if (tokenId != null) {
+
+ PreparedStatement pstmt =
connection.prepareStatement("UPDATE user_token SET date_expiry = ? WHERE id= '"
+ tokenId + "'");
+ Date actualDate = new Date();
+ Date expDate = DateUtils.addMonths(actualDate, 6);
+ pstmt.setDate(1, new java.sql.Date(expDate.getTime()));
+ pstmt.executeUpdate();
+
+ }
+
+ stmt.close();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ if (result != null)
+ result.close();
+
+ if (stmt != null)
+ stmt.close();
+
+ if (connection != null)
+ connection.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ }
+
+ private ServletRequest wrapperRequest(HttpServletRequest request, Subject
subject, Principal principal) {
+ PortalRequestWrapper wrapper = new PortalRequestWrapper(request,
subject, principal);
+ return wrapper;
+ }
+
+ public void destroy() {
+ }
+
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]