Java tutorial
/** * Copyright 2013 Tommi S.E. Laukkanen * * Licensed 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.bubblecloud.ilves.cache; import org.apache.commons.codec.binary.Base64; import org.apache.log4j.Logger; import org.bubblecloud.ilves.model.User; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Root; import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.util.List; /** * Cache for user TLS client certificates. * * @author Tommi S.E. Laukkanen */ public class UserClientCertificateCache { /** The logger. */ private static final Logger LOGGER = Logger.getLogger(UserClientCertificateCache.class); /** The entity manager factory used to access the user client certificates. */ private static EntityManagerFactory entityManagerFactory; /** * The certificate cache. */ private static InMemoryCache<Certificate, User> certificateCache = new InMemoryCache<Certificate, User>( 10 * 60 * 1000, 60 * 1000, 1000); /** * The blacklisted certificate cache. */ private static InMemoryCache<Certificate, Certificate> blacklistCache = new InMemoryCache<Certificate, Certificate>( 2 * 60 * 1000, 30 * 1000, 1000); public static void init(final EntityManagerFactory entityManagerFactory) { UserClientCertificateCache.entityManagerFactory = entityManagerFactory; } /** * Get user by certificate. * * @param clientCertificate the client certificate * @param blackListNotFound whether certificate should be blacklisted if user is not found * @return the user or null if no matching user or more than one matching user was found. */ public static synchronized User getUserByCertificate(final Certificate clientCertificate, final boolean blackListNotFound) { if (blacklistCache.get(clientCertificate) != null) { LOGGER.debug( "Blacklisted TSL client certificate: " + ((X509Certificate) clientCertificate).getSubjectDN()); return null; } final User cachedUser = certificateCache.get(clientCertificate); if (cachedUser != null) { LOGGER.debug("User matching TSL client certificate in cache: " + cachedUser.getUserId()); return cachedUser; } final String encodedCertificateString; try { encodedCertificateString = Base64.encodeBase64String(clientCertificate.getEncoded()); } catch (CertificateEncodingException e) { LOGGER.error("Error encoding TSL client certificate for finding user from database."); return null; } final EntityManager entityManager = entityManagerFactory.createEntityManager(); final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); final CriteriaQuery<User> criteria = criteriaBuilder.createQuery(User.class); final Root<User> root = criteria.from(User.class); criteria.where(criteriaBuilder.equal(root.get("certificate"), encodedCertificateString)); final TypedQuery<User> query = entityManager.createQuery(criteria); final List<User> users = query.getResultList(); if (users.size() == 1) { LOGGER.info("User found matching TSL client certificate: " + users.get(0).getUserId()); certificateCache.put(clientCertificate, users.get(0)); return users.get(0); } else if (users.size() > 1) { blacklistCache.put(clientCertificate, clientCertificate); LOGGER.error("Blacklisted TSL client certificate. More than one user had the certificate: " + clientCertificate); return null; } else { if (blackListNotFound) { blacklistCache.put(clientCertificate, clientCertificate); LOGGER.warn("Blacklisted TSL client certificate. User not found matching the certificate: " + ((X509Certificate) clientCertificate).getSubjectDN()); } else { LOGGER.warn("User not found matching the certificate: " + ((X509Certificate) clientCertificate).getSubjectDN()); } return null; } } }