/** * Copyright (c) 2013-2016, The SeedStack authors <http://seedstack.org> * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.seedstack.seed.web.security.internal; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.subject.Subject; import org.apache.shiro.web.filter.authc.AuthenticatingFilter; import org.seedstack.seed.security.X509CertificateToken; import org.seedstack.seed.security.internal.realms.AuthenticationTokenWrapper; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.security.cert.X509Certificate; /** * A security filter that extracts the certificate from the request for later use */ public class X509CertificateFilter extends AuthenticatingFilter { private static final String OPTIONAL = "optional"; private boolean optional; @Override protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception { X509Certificate[] certificates = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate"); return new AuthenticationTokenWrapper(new X509CertificateToken(certificates)); } @Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { return executeLogin(request, response); } protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) { if (optional) { return true; } try { ((HttpServletResponse) response).sendError(HttpServletResponse.SC_UNAUTHORIZED, "A valid certificate is required to gain access"); } catch (IOException e1) { throw new IllegalStateException(e1); } return false; } @Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { if (mappedValue != null && ((String[]) mappedValue).length != 0) { optional = OPTIONAL.equals(((String[]) mappedValue)[0]); } Subject subject = getSubject(request, response); return subject.isAuthenticated(); } }